How to best handle dll conflicts with revit addins

How to best handle dll conflicts with revit addins

mike.olearyZ8X6J
Explorer Explorer
4,504 Views
11 Replies
Message 1 of 12

How to best handle dll conflicts with revit addins

mike.olearyZ8X6J
Explorer
Explorer

Over the past week I have been trying to add telemetry to an internal tool that our company is creating for revit. This is a revit plugin targeting both net 8 and net framework 48 versions of revit. I'm attempting to add telemetry I had to resolve issues with version conflicts of dlls (as I expected I would). In the past we have recommended dropping support for net framework versions of tools as the net core solution is relatively simple, however, obviously this is not possible for revit as moving to newer versions can take project teams a long time (that's if they even decide to do so).

I'm wondering if anyone has discovered the silver bullet for building addins with dependencies that may be of different versions to those used by revit and/or other plugins?

What I have tried (and what I dislike/like about each solution).

  1. AssemblyLoadContext - this is by far my preferred solution but not compatible with .net framework
  2. IL-repack #1 - basically create a thin addin that calls the core assembly which is packed using IL-repack and only externalise the necessary types. This was somewhat elegant but lost the ability to hot reload
  3. IL-repack #2 - create a separate project for all my dependencies that would be packed and referenced by the addin project. I found with this solution I had to be careful referencing nuget packages as I needed to match my framework version targets. OK solution as will work with all versions of revit and hot reload will work, but build steps are kind of complicated and care needs to be taken with nuget versions as transitive dependencies would ideally match. I found that if versions of framework references do not match, the build will output the version referenced by the nuget package and would be packed resulting in the type existing both in my packed dll and as part of the framework references used in the addin project.
  4. A combination of 1 & 2 in which 1 is used for Revit >= 2025 and 2 is used for Revit <= 2024. This solution felt ok as there wasn't a great deal of branching code for handling a direct reference to a dll and using assembly load context. Hot reload would work with Revit >= 2025 but not for the IL-repack solution. 

I didn't really find the silver bullet I was looking for, and I'm tired of dealing with MSBuild. Has anyone got a better solution that I have not yet thought of?

0 Likes
4,505 Views
11 Replies
Replies (11)
Message 2 of 12

jeremy_tammik
Alumni
Alumni

Maybe... have you looked at this post explaining how RevitLookup dependency isolation achieves what you need in Revit 2025?

  

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 12

mike.olearyZ8X6J
Explorer
Explorer

@jeremy_tammik I had not read your post. But AssemblyLoadContext is only available in .net core (Revit 2025). As I mentioned this is my preferred solution, and although I did not use the package that is mentioned in your post this is reasonably easy to wire up, the issue is; this is only a solution for Revit 2025. I am after a solution for .net framework.

I didn't mind having the 2 solutions managed by configurations targeting specific Revit versions although this is still less than ideal and the simplest solution I could come up with for .net framework (option #2), means that hot reload won't work on older Revit version. I only really require this as drafters will largely be writing the code and I feel that hot reload is invaluable to someone learning C#.

0 Likes
Message 4 of 12

jeremy_tammik
Alumni
Alumni

Indeed, your approach sounds good to me.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 12

ricaun
Advisor
Advisor

I'm not a big fun of the AssemblyLoadContext, makes the code kinda complex. Maybe one day Autodesk implement some kinda of isolation directly inside Revit, using AssemblyLoadContext probably.

 

IL-repack is the way, I don't know what do you mean by hot reload. At least I never IL-repack the plugin when developing only on the Release.

 

The option to repack all the dependencies in as single dependence is a good option, I some times repack a single package just to reuse inside Revit.

I did something like that with the HelixToolkit a long time ago: https://github.com/ricaun-io/ricaun.HelixToolkit.Wpf

 

Anyway I did some experiments in RevitLookUp to ILRepack to fix some issues and to remove all the dependencies inside my machine.

 

I create a package to help me to ILRepack the plugin, still missing some features, but the basic already works.

 

This is the configuration I'm using in the .csproj inside the RevitLookup.

<ItemGroup>
    <PackageReference Include="ricaun.ILRepack" Version="1.0.0-rc" />
    <ILRepackIgnoreReferences Include="RevitLookup.UI.dll" />
</ItemGroup>

<PropertyGroup>
    <ILRepackImportance>High</ILRepackImportance>
    <ILRepackCommandImportance>High</ILRepackCommandImportance>
    <ILRepackCommandExtra>/union /allowduplicateresources</ILRepackCommandExtra>
</PropertyGroup>

 

Even after Revit release some kind of isolation, I probably gonna still use ILRepack to release plugins/packages.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 6 of 12

Moustafa_K
Advisor
Advisor

Handling DLL conflicts in Revit add-ins can indeed be challenging, especially when different plugins require different versions of the same library. After experimenting with several approaches, one method that has worked for me in specific scenarios is using AppDomains to isolate dependencies. This technique allows each add-in to load its required DLLs independently, avoiding conflicts with Revit’s internal dependencies or other plugins.

 

see this example:

 

(view in My Videos)

 

The issue arose with a specific DLL already included in Revit’s libraries but required an advanced version for my add-in. After simplifying the case to better understand the root cause, I successfully resolved it using AppDomains.

 

Metaphorically, think of AppDomains in Revit as placing a fish (the conflicting DLL) into a water-filled, transparent sack (the isolated AppDomain) inside a larger aquarium (Revit’s Default AppDomain). The fish swims freely in its own water without disturbing the rest of the tank. Similarly, the isolated AppDomain allows the DLL to operate with its specific version requirements without impacting Revit’s internal environment or other add-ins. This “sack in an aquarium” approach maintains harmony while meeting the unique needs of each element.

 

If you’re interested, I’ve explained this solution in detail on my blog:
Using AppDomains to Resolve DLL Conflicts in Revit Plugins.

 

You can also check out a working project sample on GitHub that might help in your case.

 

I’d love to hear your findings or discuss any challenges you face!

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 7 of 12

mike.olearyZ8X6J
Explorer
Explorer
I don't know what do you mean by hot reload.

Introducing the .NET Hot Reload experience for editing code at runtime - .NET Blog
By hot reload I am referring to the ability to make changes to code when debugging and have them immediately apply, this is much more preferable than unloading and reloading dlls. I posted an issue on IL-Repack github with a simple console app in which hot reload fails to work once packed. Because these developers are just starting out (background is drafting), I feel that hot reload functionality is a must have.




0 Likes
Message 8 of 12

mike.olearyZ8X6J
Explorer
Explorer

Ok I did actually try this to, although I did not mention it as I figured it was never going to work. The issue I ran into was that I needed to marshal revit object across app domains and could not get this to work (nor did I think it was safe to do so). I don't see an example in your code in which CommandData for example is passed between domains. The reality is we can't decouple our addin from using revit objects.

If there is a solution to this, I would love to know it as I have had no luck.

0 Likes
Message 9 of 12

mike.olearyZ8X6J
Explorer
Explorer

Oh also I saw a video you posted on youtube with an AssemblyLoadContext example. Just FYI it wasn't quite right, in your example you shouldn't be loading many contexts for accessing commands which resulted in odd behaviour like static variables not maintaining state. The code I wrote to do this loading all types upfront in the same context, so all commands etc that were resolved are in the same context. It meant that a single context was created on app startup. Imo I still way more prefer this than ILRepack as ILRepack won't always place nice depending on how you set it up. If you pack the whole addin I don't think there will be any issues, but if you pack say a core library to be consumed by the addin project you do need to be careful with framework references and matching versions of these, otherwise the framework reference may get pack in the core library and won't match the type in the addin library.

0 Likes
Message 10 of 12

ricaun
Advisor
Advisor

@mike.olearyZ8X6J wrote:
I don't know what do you mean by hot reload.

Introducing the .NET Hot Reload experience for editing code at runtime - .NET Blog
By hot reload I am referring to the ability to make changes to code when debugging and have them immediately apply, this is much more preferable than unloading and reloading dlls. I posted an issue on IL-Repack github with a simple console app in which hot reload fails to work once packed. Because these developers are just starting out (background is drafting), I feel that hot reload functionality is a must have.



Never manage to make the Hot Reload to work well inside Revit, I use the unloading and reloading dll approach using my AppLoader plugin. I only use IL-Repack when releasing the package/plugin, for developing is kinda overkill, and depending of the project IL-Repack take some time to finish.


@mike.olearyZ8X6J wrote:

Oh also I saw a video you posted on youtube with an AssemblyLoadContext example. Just FYI it wasn't quite right, in your example you shouldn't be loading many contexts for accessing commands which resulted in odd behaviour like static variables not maintaining state. The code I wrote to do this loading all types upfront in the same context, so all commands etc that were resolved are in the same context. It meant that a single context was created on app startup. Imo I still way more prefer this than ILRepack as ILRepack won't always place nice depending on how you set it up. If you pack the whole addin I don't think there will be any issues, but if you pack say a core library to be consumed by the addin project you do need to be careful with framework references and matching versions of these, otherwise the framework reference may get pack in the core library and won't match the type in the addin library.


I don't know what video you saw, but I pretty sure I create a single AssemblyLoadContext for the plugin. And all the IExternalCommand need to find this AssemblyLoadContext to execute the command inside that context to use the same dll reference.

 

I prefer IL-Repack that does not introduce any code complexity inside the plugin, especially because I can apply IL-Repack in a nuget package (.nupkg) to remove the third party dependencies and make a single dll to work inside Revit, and as a .nupkg the compiler only gonna allow the correct target framework.

 

And eventually Autodesk will release some kind of isolation, probably using AssemblyLoadContext natively inside Revit loading addin process. I would not bother to use AssemblyLoadContext inside a Revit addin if IL-Repack in most case works.

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 11 of 12

mike.olearyZ8X6J
Explorer
Explorer

Sorry the video was this one RevitLookup - End of DLL hell - Revit API. I'm not sure if the intention was to show loading multiple different contexts, but at the end of the video you should how adding a static class with static property is updated separately from either button. The issue here is that each button seems to effectively have its own context. I would find this behaviour odd as a developer and can be resolved by simply having a single context. When I tested out this approach, I needed a single context which avoids the same dll being spread across multiple contexts. Again I still think this is a much better approach t IL-repack as there is no real downsides, unlike IL-repack which comes with build times and caution about using versions of framework references that aren't compatible between projects.

As for hot reload I find it works really well, at least I have not run into any issues yet.

And finally, yes I agree, it would have been much more ideal if Revit were loading the addins in a separate context as this would avoid a lot of headache for developers, and in my opinion should have been done as part of the .net core support being added.

0 Likes
Message 12 of 12

ricaun
Advisor
Advisor

I guess in the video there is two context, the default Revit context and new Addin context.

By default Revit always creates the IExternalCommand in the default context. And that command finds the new Addin context already created in the IExternalApplication to re-execute the IExternalCommand in the correct context with all the dependencies loaded in there. The idea is to only use the new Addin context, I suppose you are doing some similar.

 


@mike.olearyZ8X6J wrote:
And finally, yes I agree, it would have been much more ideal if Revit were loading the addins in a separate context as this would avoid a lot of headache for developers, and in my opinion should have been done as part of the .net core support being added.

 

Yes, Autodesk missed the opportunity to launch in Revit 2025, maybe next version happen. There is something in the Revit Preview.

I already tested, and I can't discuss outside Revit Preview forum. If you want to know how that is working follow the link.

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes