Host guide
License a Revit add-in
Build the add-in for the exact Revit runtime, register the matching binary, then tie one Drawspan handle to the add-in lifecycle.
Choose the target from the Revit update
Build against the framework and RevitAPI.dll belonging to the exact Revit update you support. The release year alone is no longer enough.
Revit 2024
net48
Reference Revit 2024\RevitAPI.dll.
Manifest folder: Addins\2024.
Revit 2025.0–2025.4.6
net8.0-windows
Reference Revit 2025\RevitAPI.dll.
Manifest folder: Addins\2025.
Revit 2026.5
net10.0-windows
Reference the updated Revit 2026\RevitAPI.dll.
Manifest folder: Addins\2026.
Autodesk documents .NET Framework 4.8 for Revit 2024, net8.0-windows and a rebuild for Revit 2025, and the move to .NET 10 in Revit 2026.5. Revit 2026.0–2026.4 used .NET 8 before the in-place 2026.5 update. Revit 2025.5 also moves the 2025 release line to .NET 10.
Build each add-in
Install Drawspan.Client.V1 from NuGet into your add-in project. Choose the target framework and API references for the installed Revit update. For example, a project targeting Revit 2026.5 can use:
<PropertyGroup>
<TargetFramework>net10.0-windows</TargetFramework>
<AssemblyName>AcmeTools</AssemblyName>
<RevitDir>C:\Program Files\Autodesk\Revit 2026</RevitDir>
</PropertyGroup>
<ItemGroup>
<Reference Include="RevitAPI">
<HintPath>$(RevitDir)\RevitAPI.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="RevitAPIUI">
<HintPath>$(RevitDir)\RevitAPIUI.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>Adjust RevitDir for your installation. Build each supported version with its matching framework and API references; a shared framework does not make different years' API assemblies interchangeable.
dotnet build AcmeTools.Revit.csproj -c ReleaseKeep Private set to false for RevitAPI and RevitAPIUI; Revit supplies them. Do not include either assembly in your installer.
Copy package dependencies into the build output
A modern .NET add-in is a class library, so package assemblies are not copied to its output by default. Set CopyLocalLockFileAssemblies in the add-in project. It copies runtime assets from the NuGet lock file, including transitive package dependencies, into the folder that you deploy.
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>A PackageReference only makes Drawspan.Client.V1 available while compiling. The setting above makes Drawspan.Client.V1.dll part of the build output. Your installer must then keep it beside the add-in assembly.
Your deployable files should follow this layout. The .pdb files are useful for diagnostics but are not required to load the add-in.
net48\
AcmeTools.dll
Drawspan.Client.V1.dll
AcmeTools.pdb # optional
net8.0-windows\ or net10.0-windows\
AcmeTools.dll
AcmeTools.deps.json
Drawspan.Client.V1.dll
AcmeTools.pdb # optionalRegister each build
A .addin file does not declare a target framework. Its year-specific folder and Assembly path select the binary. Autodesk documents the per-user and all-user manifest locations.
%APPDATA%\Autodesk\Revit\Addins\2024\AcmeTools.addin -> ...\net48\AcmeTools.dll
%APPDATA%\Autodesk\Revit\Addins\2025\AcmeTools.addin -> ...\net8.0-windows\AcmeTools.dll
%APPDATA%\Autodesk\Revit\Addins\2026\AcmeTools.addin -> ...\net10.0-windows\AcmeTools.dllThe XML shape is the same in each file; change the assembly path to the matching build:
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Name>Acme Tools</Name>
<Assembly>C:\Program Files\Acme Tools\Revit 2026\AcmeTools.dll</Assembly>
<AddInId>604B1052-F742-4951-8576-C261D1993107</AddInId>
<FullClassName>AcmeTools.App</FullClassName>
<VendorId>ACME</VendorId>
</AddIn>
</RevitAddIns>Keep each manifest separate from the binary folder. A production installation can use this layout:
%APPDATA%\Autodesk\Revit\Addins\2026\AcmeTools.addin
C:\Program Files\Acme Tools\Revit 2026\
AcmeTools.dll
AcmeTools.deps.json
Drawspan.Client.V1.dll
AcmeTools.pdb # optionalThe manifest's Assembly value must point to AcmeTools.dll in that folder. During development, it can instead point to your matching bin\Release\<TFM> output. Keep one manifest per supported Revit year.
Close Revit before replacing an installation
Revit can keep loaded assemblies locked until the process exits. Close every Revit process using the add-in before replacing its binary folder or manifest, then start Revit again to test the new files.
Revit reads .addin files from both the per-user and all-user locations at startup. An old manifest in either location can keep loading an old binary. Locate manifests that reference your assembly before deleting anything:
$roots = @(
"$env:APPDATA\Autodesk\Revit\Addins",
"$env:ProgramData\Autodesk\Revit\Addins"
)
Get-ChildItem -LiteralPath $roots -Filter '*.addin' -File -Recurse -ErrorAction SilentlyContinue |
Select-String -SimpleMatch 'AcmeTools.dll' |
Select-Object Path, LineInspect every result and its Assembly path. Remove only manifests and binary folders that belong to the stale Acme Tools installation, then install one manifest per supported Revit year. Autodesk documents both manifest roots.
Do not confuse building with loading
Building source against an API establishes a supported output. It is not the same test as asking a newer runtime to load an existing binary. Autodesk says an existing .NET 8 add-in may continue under .NET 10 unless a .NET 10 breaking change affects it. Host-test that binary; do not turn the possibility into a support promise.
A load-time mismatch may appear only as Revit's generic “add-in could not be loaded” message or as a missing or incompatible assembly error. Build and host-test every binary you ship.
Own the handle in IExternalApplication
Own one handle in IExternalApplication, start it from OnStartup, and dispose it from OnShutdown.
Gate every IExternalCommand
Read the current Status inside each IExternalCommand before protected work begins.
Keep Revit API calls on its UI thread
Marshal UI updates through the host's supported mechanism, then check Status again when the external command runs.
Continue with the integration examples
Client lifecycle example · Protect a command · Vendor configuration