I have a third party (licensing client) dll I need to include in my Add-In. How do I make sure this file is included in my Add-Ins esriAddinX file? It is not a .Net dll so I cannot easily include it as part of my Add-In solution.
I ended up using SetDllDirectory to augment the DLL search paths with the cache directory so that the existing DllImport directives would find the dll. This worked just great. Thanks for all of your help!
Also some 3rd party libraries provide methods to change load location for any dlls or subprocesses. For example i wrote a sample using CefSharp which required this initialization code before i was able to use the control:
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="operator token">!</SPAN>Cef<SPAN class="punctuation token">.</SPAN>IsInitialized<SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN> <SPAN class="keyword token">var</SPAN> settings <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">CefSettings</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN> <SPAN class="comment token">//By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data</SPAN> CachePath <SPAN class="operator token">=</SPAN> System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Combine</SPAN><SPAN class="punctuation token">(</SPAN>Environment<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetFolderPath</SPAN><SPAN class="punctuation token">(</SPAN>Environment<SPAN class="punctuation token">.</SPAN>SpecialFolder<SPAN class="punctuation token">.</SPAN>LocalApplicationData<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"CefSharp\\Cache"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> BrowserSubprocessPath <SPAN class="operator token">=</SPAN> System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Combine</SPAN><SPAN class="punctuation token">(</SPAN>System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetDirectoryName</SPAN><SPAN class="punctuation token">(</SPAN>System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetFullPath</SPAN><SPAN class="punctuation token">(</SPAN>Assembly<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetExecutingAssembly</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>Location<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"CefSharp.BrowserSubprocess.exe"</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="comment token">//Perform dependency check to make sure all relevant resources are in our output directory.</SPAN> Cef<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Initialize</SPAN><SPAN class="punctuation token">(</SPAN>settings<SPAN class="punctuation token">,</SPAN> performDependencyCheck<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">true</SPAN><SPAN class="punctuation token">,</SPAN> browserProcessHandler<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="punctuation token">}</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
Add these lines in your Module class (this constructor should be called first) - rename Module1 to the name of your Module class:
<SPAN class="keyword token">public</SPAN> <SPAN class="token function">Module1</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN> AppDomain currentDomain <SPAN class="operator token">=</SPAN> AppDomain<SPAN class="punctuation token">.</SPAN>CurrentDomain<SPAN class="punctuation token">;</SPAN> currentDomain<SPAN class="punctuation token">.</SPAN>AssemblyResolve <SPAN class="operator token">+</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">ResolveEventHandler</SPAN><SPAN class="punctuation token">(</SPAN>ResolveProAssemblyPath<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="punctuation token">}</SPAN> <SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
And add this method to the module class:
<SPAN class="keyword token">static</SPAN> System<SPAN class="punctuation token">.</SPAN>Reflection<SPAN class="punctuation token">.</SPAN>Assembly <SPAN class="token function">ResolveProAssemblyPath</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="keyword token">object</SPAN> sender<SPAN class="punctuation token">,</SPAN> ResolveEventArgs args<SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN> <SPAN class="keyword token">string</SPAN> folderPath <SPAN class="operator token">=</SPAN> System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetDirectoryName</SPAN><SPAN class="punctuation token">(</SPAN>System<SPAN class="punctuation token">.</SPAN>IO<SPAN class="punctuation token">.</SPAN>Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetFullPath</SPAN><SPAN class="punctuation token">(</SPAN>System<SPAN class="punctuation token">.</SPAN>Reflection<SPAN class="punctuation token">.</SPAN>Assembly<SPAN class="punctuation token">.</SPAN><SPAN class="token function">GetExecutingAssembly</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>Location<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">string</SPAN> assemblyPath <SPAN class="operator token">=</SPAN> Path<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Combine</SPAN><SPAN class="punctuation token">(</SPAN>folderPath<SPAN class="punctuation token">,</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">System<SPAN class="punctuation token">.</SPAN>Reflection<SPAN class="punctuation token">.</SPAN>AssemblyName</SPAN><SPAN class="punctuation token">(</SPAN>args<SPAN class="punctuation token">.</SPAN>Name<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>Name <SPAN class="operator token">+</SPAN> <SPAN class="string token">".dll"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="operator token">!</SPAN>File<SPAN class="punctuation token">.</SPAN><SPAN class="token function">Exists</SPAN><SPAN class="punctuation token">(</SPAN>assemblyPath<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">return</SPAN> <SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">;</SPAN> System<SPAN class="punctuation token">.</SPAN>Reflection<SPAN class="punctuation token">.</SPAN>Assembly assembly <SPAN class="operator token">=</SPAN> System<SPAN class="punctuation token">.</SPAN>Reflection<SPAN class="punctuation token">.</SPAN>Assembly<SPAN class="punctuation token">.</SPAN><SPAN class="token function">LoadFrom</SPAN><SPAN class="punctuation token">(</SPAN>assemblyPath<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="keyword token">return</SPAN> assembly<SPAN class="punctuation token">;</SPAN> <SPAN class="punctuation token">}</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
Set a breakpoint in the static method to make sure it gets called before your dll is loaded and double check the path. Needless to say this all depends on the loading method that is used for your 3rd party dll and only works if the load failure event is triggered.
That got me one step closer. Now the DLL is in the Install directory inside of the esriAddinX file, but ArcPro fails with 'Unable to load DLL'. I checked the assembly cache and the dll is there as well. Could you give me a little more detail for how we would force this dll to be resolved? Thanks!
Here is a piece of code that helps to resolve the DLL path is needed:
https://github.com/Esri/arcgis-pro-sdk/wiki/ProGuide-content-and-image-resources#images-as-embedded-resources
If you can't add a reference for the 3rd party DLL to your project, you can always add the DLL to your project as an 'existing item' (note: you can do that to any file type you'd like to add to your add-in payload) Make sure that the DLL's build action is set to 'Content' and 'copy to output directory' is set to 'Copy ...'. At run time, just before your add-in is executed by Pro, ArcGIS Pro will unzip the content of your add-in package as described here: https://github.com/esri/arcgis-pro-sdk/wiki/ProConcepts-Advanced-Topics#loading-3rd-party-assembly-references
If the 3rd party DLL doesn't get loaded in ArcGIS Pro during runtime you can resolve the DLL's path by adding a handler to do so:
AppDomain currentDomain <SPAN class="operator token">=</SPAN> AppDomain<SPAN class="punctuation token">.</SPAN>CurrentDomain<SPAN class="punctuation token">;</SPAN> currentDomain<SPAN class="punctuation token">.</SPAN>AssemblyResolve <SPAN class="operator token">+</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="keyword token">new</SPAN> <SPAN class="token class-name">ResolveEventHandler</SPAN><SPAN class="punctuation token">(</SPAN>ResolveProAssemblyPath<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN></SPAN>
Aangemelde leden kunnen berichten plaatsen, updates volgen en meer. Nieuw hier? Registreer een gratis account.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.