If we have two versions of a plugin both of which uses different versions of a common DLL, after running the older version of the plug-in loaded in Revit, it loads up the older version of the dependent common type library. After this, if we run the other plug-in which references another version of the same dependent DLL, Revit throws an exception. How can we resolve this?
To give an example, lets us create two plugins, A and B and both reference a common DLL called LibraryL which is used with the option "Copy Local" to be true in Visual Studio. The problem comes when we refactor LibraryL in plug-in B solution.
Now if we run plugin A first, it loads old version of Library L (it was copied locally in its bin\Debug folder). Next, we try to run plugin B, which needs library L, but since its already loaded in Revit, the older version of this library is used and plugin B cannot work since it needs the new Library L to work.
What is often desired is that each plug-in uses its local copy of the library L instead of reusing the one of an other plug-in. How can we make this possible?
To resolve this, we should create strong name for the common DLLs to work with simultaneously - merely having a different version number for the common type library does not work.
Note: Since Revit API dlls are not strong named, the following approach only works if the common type library project themselves do not reference the Revit API dlls.
If the common type library projects are not themselves referencing the Revit API dlls, we can generate strong names for both the versions of the same common DLL to be able to work with them simultaneously. Following is what should be done:
- Use sn.exe tool to generate unique strong name keys for different versions of the common DLL (LibraryL project in your case). In the Start Menu program, click on Visual Studio Tools and open the Visual Studio x64 Win64 Command Prompt and type in *sn.exe –k c:\Temp\test1.snk*. You can read up more on the parameters but as overview we are using this command to use the sn.exe and specifying that we want to create a key and save it in a file called test1.snk in the temp folder.
- Now, move this test1.snk into the LibraryL project. In the AssemblyInfo.cs file of project LibraryL, add the following attribute called AssemblyKeyFileAttribute and include the strong name key file name (test1.snk) file that we have just moved to. For example, the following screenshot shows how the attribute should read like.
- Now build ProjectA and close it
- Open Project B, make the changes in method name in LibraryL and make corresponding changes to Project B code.
- Use the sn.exe tool to generate another unique key, name it test2.snk and move that key to the LibraryL project.
- Now in LibraryL’s assemblyInfo.cs file, change the newly created AssemblyKeyFileAttribute to point to the test2.snk file.
- Build ProjectB and run it in debug mode
- In Revit UI, since you have the manifest files already being created, click on Command A and then you will see the task dialog and then click on command B and you will be able to see the task dialog again (and not the error we were getting before).
The updated complete VS project (with sn keys) is provided here.
Just a note that when you run sn.exe, you might get a *keyset not defined* error. This error occurs with the Cryptographic Service Provider. And to resolve it, you can type in *sn.exe –c* to reset to default values and then use the *sn.exe –k <key filename>* command to generate the strong name key.
This entire behavior is not specific to Revit nor its API but is generic .NET behavior. If you need more information on this, you can read up on the many articles online (and on MSDN) related to this.