Revit API - Possible NewtonSoft.Json conflict

爷,独闯天下 提交于 2019-12-08 12:47:28

First, I will start with the Fuslogvw.exe tool to see what happens when your assembly is loaded.

AddInManager use Assembly.LoadFile to load the addin, then hook into the AppDomain.CurrentDomain.AssemblyResolve event to resolve the dependencies. May be you can use the same technique to load your Newtonsoft.Json assembly.

I manually load all of my dependencies in the IExternalApplication.OnStartup method. The problem you're experiencing is because Revit looks in the folder containing Revit.exe for any dependencies and not in your addin directory.

If you can't get the AssemblyResolve event to work, then try something like this:

Retrieve the directory of your addin by using string location = Assembly.GetAssembly(typeof(YourIExternalApplicationClass)).Location;, then use string dir = Path.GetDirectoryName(location);

You can then get the path of each dependency by using string dllPath = Path.Combine(dir, "DLLName.dll");

Finally, load each DLL by using Assembly.LoadFrom(dllPath);

I did a bit more research because I did not fully understand the solution above. I thought a really simple solution was explained here

You just set the reference (newtonsoft.json) to specific version = true in your visual studio project, and then copy over that reference into the add-in folder with your revit add-in .dll

When you distribute to users they would need the newtonsoft.json library as well as your add-in .dll which isn't ideal but workable (just tested and this worked for me)

So I similarly had this issue in a project that I'm working on. After a substantial amount of digging on the issue I feel like I have a strong grasp on what is happening.

As was stated, Revit loads assemblies using the Assembly.LoadFile command. This means that all the add-in assemblies are loaded into the same AppDomain. That's not ideal given if you want to add an event handler to AppDomain.CurrentDomain.AsseblyResolve in order to prevent conflict in your add-in. This is because AssemblyResolve is an unusual event which requires an Assembly as the return item. That means that if you have multiple event handlers attached to AssemblyResolve then the first event handler that returns a non null Assembly will be the event handler that is used and thus cause conflict if multiple add-ins are attempting to resolve the same Assembly (such in the case of a common Assembly like Newtonsoft.Json).

So for instance, and example that would likely be common among programmers, if you have Dynamo installed, Dynamo ALSO adds an event handler to AssemblyResolve that attempts to resolve Newtonsoft.Json and loads it from the Dynamo program files directory when called. In my case, I needed Newtonsoft.Json version 7.0.0.0 but with Dynamo 0.9 installed on my computer it was returning Newtonsoft.Json version 4.5.0.0. This was incredibly confusing given I had theoretically handled the resolution perfectly but my assembly resolve event was not firing when I needed it to.

With all that said, there isn't too much that you can do in this certain instance. A few round-about ways to defeat this problem are:

-Find a way to load your add-in prior to Dynamo (or whichever Assembly is resolving the event that you wish to resolve) and handle the resolution better (i.e. make sure it's your application that is currently being run prior to resolving the assembly issue). NOTE: Having looked at the procmon.exe output at the startup of Revit it appears that Revit loads addins from the "C:\ProgramData\Autodesk\Revit\Addins\" folder first, in alphabetical order, AND THEN from the "C:\ProgramData\Autodesk\ApplicationPlugins" folder in alphabetical order.

-Contact the conflicting add-in manufacturer and ask them kindly to fix the resolution.

-Specific to my issue, simply upgrading dynamo to version 1.2 solved the conflict.

I've read about creating your own AppDomain and loading all the assemblies that you need into it and then perform the operations you want without conflict, but I couldn't get it to work for myself.

Note: Don't waste time messing with the application.config file for your specific library. Revit will only check the Revit.exe.config for the Assembly probing path and dependent assembly information. I also wouldn't recommend modifying that.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!