Upgrading a Revit Macro to a Revit Extension involves adapting your existing code to the new extension model used by Assistant. This guide will walk you through the changes you need to make and help you transition seamlessly.
The same prinsiples goes for Tekla, AutoCAD, Navisworks macros as well
Execute method is replaced by the Run method.TextExtensionResult, which provides a more structured response.Run instead of Execute.TextExtensionResult in your method..csproj to the new standardConfigurations.targets file and paste the content shown belownuget.config fileReadme.md to this wiki, see process here Writing help files for ExtensionsThe following example macro is changed from this
public class RevitMacroCommand : IExternalCommand
{
public RevitMacroArgs Args { get; set; }
public Action<string> Log { get; set; }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var document = commandData.Application.ActiveUIDocument.Document;
try
{
// Exsisting code
return Result.Succeeded;
}
catch (Exception exception)
{
Log("Log this error:" + exception);
return Result.Failed;
}
}
}
to this
public class RevitExtensionCommand : IRevitExtension<RevitExtensionArgs>
{
public IExtensionResult Run(IRevitExtensionContext context, RevitExtensionArgs args, CancellationToken cancellationToken)
{
var document = context.UIApplication.ActiveUIDocument?.Document;
// Exsisting code
// Create a message with the input text
var message = $"Input = {args.TextInput}";
// Return a result with the message
return Result.Text.Succeeded(message);
}
}
Is changed from this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<DebugType>portable</DebugType>
<AssemblyName>RevitMacro</AssemblyName>
<NoWarn>NU1701</NoWarn>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<PackageId>RevitMacro.Macro</PackageId>
<PackageProjectUrl>https://cowi-tools.visualstudio.com/COWI-Tools%20Macros/_git/RevitMacro</PackageProjectUrl>
<RepositoryUrl>https://cowi-tools.visualstudio.com/COWI-Tools%20Macros/_git/RevitMacro</RepositoryUrl>
<Authors>Tools</Authors>
<Company>MyCompany</Company>
<Version>0.0.1</Version>
<Product>RevitMacro Macro</Product>
<Description>RevitMacroDescription</Description>
<PackageTags>Revit;Assistant;Macro</PackageTags>
<PackageIconUrl>...</PackageIconUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CW.Macro.Core" Version="0.0.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
<PackageReference Include="Revit.RevitApi.x64" Version="2019.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
<PackageReference Include="Revit.RevitApiUI.x64" Version="2019.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
to this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ExtensionId>RevitAutomationExtension</ExtensionId>
<Authors>Tools</Authors>
<Version>0.0.1</Version>
<Title>RevitAutomationExtension</Title>
<Description>RevitAutomationExtension Description</Description>
<PackageTags>Revit;Assistant;Extension</PackageTags>
<PackageIcon>Icon.png</PackageIcon>
<PackageIconUrl></PackageIconUrl>
<!--
Adjust MainRevitVersion to get IntelliSense for the correct version do a
dotnet restore to restore the correct nuget packages for the selected Revit version.
-->
<MainRevitVersion Condition="'$(Configuration)' == 'Debug'">2024</MainRevitVersion>
<LangVersion>12</LangVersion>
</PropertyGroup>
<Import Project=".\Configurations.targets" />
<ItemGroup>
<None Include="Icon.png" Pack="true" PackagePath="" />
</ItemGroup>
</Project>
The new project standard has this line: <Import Project=".\Configurations.targets" />
The content of the new file is as following:
<Project>
<PropertyGroup>
<PlatformTarget>x64</PlatformTarget>
<DebugType>portable</DebugType>
<Nullable>enable</Nullable>
<NoWarn>NU1701</NoWarn>
<Configurations>Debug;Debug 2019;Debug 2020;Debug 2021;Debug 2022;Debug 2023;Debug 2024;Debug 2025;Debug 2026;Release 2019;Release 2020;Release 2021;Release 2022;Release 2023;Release 2024;Release 2025;Release 2026</Configurations>
</PropertyGroup>
<Choose>
<When Condition="$(Configuration.Contains('2019')) or $([System.String]::Equals('$(MainRevitVersion)', '2019'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2019</MainRevitVersion>
<RevitVersion>2019.0.1</RevitVersion>
<DefineConstants>R2019;R2019_OR_GREATER;R2019_OR_LESS;R2020_OR_LESS;R2021_OR_LESS;R2022_OR_LESS;R2023_OR_LESS;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2020')) or $([System.String]::Equals('$(MainRevitVersion)', '2020'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2020</MainRevitVersion>
<RevitVersion>2020.0.1</RevitVersion>
<DefineConstants>R2020;R2019_OR_GREATER;R2020_OR_GREATER;R2020_OR_LESS;R2021_OR_LESS;R2022_OR_LESS;R2023_OR_LESS;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2021')) or $([System.String]::Equals('$(MainRevitVersion)', '2021'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2021</MainRevitVersion>
<RevitVersion>2021.1.4</RevitVersion>
<DefineConstants>R2021;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2021_OR_LESS;R2022_OR_LESS;R2023_OR_LESS;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2022')) or $([System.String]::Equals('$(MainRevitVersion)', '2022'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2022</MainRevitVersion>
<RevitVersion>2022.1.0</RevitVersion>
<DefineConstants>R2022;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2022_OR_GREATER;R2022_OR_LESS;R2023_OR_LESS;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2023')) or $([System.String]::Equals('$(MainRevitVersion)', '2023'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2023</MainRevitVersion>
<RevitVersion>2023.0.0</RevitVersion>
<DefineConstants>R2023;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2022_OR_GREATER;R2023_OR_GREATER;R2023_OR_LESS;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2024')) or $([System.String]::Equals('$(MainRevitVersion)', '2024'))">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<MainRevitVersion>2024</MainRevitVersion>
<RevitVersion>2024.0.0</RevitVersion>
<DefineConstants>R2024;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2022_OR_GREATER;R2023_OR_GREATER;R2024_OR_GREATER;R2024_OR_LESS;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2025')) or $([System.String]::Equals('$(MainRevitVersion)', '2025'))">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<MainRevitVersion>2025</MainRevitVersion>
<RevitVersion>2025.0.0</RevitVersion>
<DefineConstants>R2025;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2022_OR_GREATER;R2023_OR_GREATER;R2024_OR_GREATER;R2025_OR_GREATER;R2025_OR_LESS;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
<When Condition="$(Configuration.Contains('2026')) or $([System.String]::Equals('$(MainRevitVersion)', '2026'))">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<MainRevitVersion>2026</MainRevitVersion>
<RevitVersion>2026.0.0</RevitVersion>
<DefineConstants>R2026;R2019_OR_GREATER;R2020_OR_GREATER;R2021_OR_GREATER;R2022_OR_GREATER;R2023_OR_GREATER;R2024_OR_GREATER;R2025_OR_GREATER;R2026_OR_GREATER;R2026_OR_LESS</DefineConstants>
</PropertyGroup>
</When>
</Choose>
<PropertyGroup Condition="$(Configuration.Contains('Debug'))">
<OutputPath>.\bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>$(ExtensionId).$(MainRevitVersion).$(Version)</AssemblyName>
</PropertyGroup>
<PropertyGroup>
<PackageId>$(ExtensionId).$(MainRevitVersion)</PackageId>
</PropertyGroup>
<Choose>
<When Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<ItemGroup >
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
</When>
<Otherwise>
<PropertyGroup>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Otherwise>
</Choose>
<ItemGroup>
<PackageReference Include="Revit_All_Main_Versions_API_x64" Version="$(RevitVersion)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
<PackageReference Include="CW.Assistant.Extensions.Revit.$(MainRevitVersion)" Version="5.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
<PackageReference Include="PolySharp" Version="1.14.1" Condition="'$(TargetFramework)' == 'net48'">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
The following nuget source needs to be added to the nuget.config file:
<add key="cowi-tools-public" value="https://pkgs.dev.azure.com/cowi-tools/f7c2ca28-a7af-4180-a54e-2cfc099d4e0e/_packaging/cowi-tools-public/nuget/v3/index.json" />
The result file should look like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="cowi-tools-public" value="https://pkgs.dev.azure.com/cowi-tools/f7c2ca28-a7af-4180-a54e-2cfc099d4e0e/_packaging/cowi-tools-public/nuget/v3/index.json" />
</packageSources>
</configuration>
In folder .vscode add a new file tasks.json. This enables the build configuration, see Building your extension for more details
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Revit 2019",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2019"
],
"group": "build"
},
{
"label": "Revit 2020",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2020"
],
"group": "build"
},
{
"label": "Revit 2021",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2021"
],
"group": "build"
},
{
"label": "Revit 2022",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2022"
],
"group": "build"
},
{
"label": "Revit 2023",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2023"
],
"group": "build"
},
{
"label": "Revit 2024",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2024"
],
"group": "build"
},
{
"label": "Revit 2025",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2025"
],
"group": "build"
},
{
"label": "Revit 2026",
"command": "dotnet",
"args": [
"publish",
"-c",
"Debug 2026"
],
"group": "build"
}
]
}
GlobalUsings.cs
// Global using directives - these are available throughout the entire project
// .NET Core Framework namespaces
global using System;
global using System.Linq;
global using System.ComponentModel;
global using System.Threading;
global using System.Threading.Tasks;
global using System.Collections.Generic;
// Assistant Extension Framework - Type alias
global using Result = CW.Assistant.Extensions.Contracts.Result;
// Assistant Extension Framework namespaces
global using CW.Assistant.Extensions.Contracts;
global using CW.Assistant.Extensions.Contracts.Enums;
global using CW.Assistant.Extensions.Contracts.Attributes;
global using CW.Assistant.Extensions.Contracts.Collectors;
// Revit-specific extension framework namespaces
global using CW.Assistant.Extensions.Revit;
global using CW.Assistant.Extensions.Revit.Attributes;
global using CW.Assistant.Extensions.Revit.Collectors;
// Autodesk Revit API namespaces
global using Autodesk.Revit.DB;
global using Autodesk.Revit.UI;
In folder .vscode add a new file settings.json with the following content. This dissable automatic restore, as it does not work with configurations for the integration version.
{
"dotnet.projects.enableAutomaticRestore": false,
"dotnet.automaticallyCreateSolutionInWorkspace": false
}