Reputation: 305
I am making an XLL using C# with ExcelDNA, and all works fine so far apart from one thing - I have to call a 3rd-party DLL (also developed in .NET in C#) and that I am certain is installed (with admin privileges) to a fixed absolute path on all user machines.
When I add a reference to the DLL to my csproj file (by Browsing to the DLL on my machine), it all seems to work (when I add the required 'using' statement), except that my csproj file adds a relative path to the HintPath field for the reference.
How do I add the DLL as a reference that will always be looked for in an absolute location?
The relevant section of my csproj file looks like (when it seems to work):
<ItemGroup>
<Reference Include="SIMExporterEbmlImport">
<HintPath>..\..\..\..\..\..\ProgramData\EB Bridging Tools\SimExporter\SIMExporterEbmlImport.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
And then I can do this in my actual code:
using SIMExporterEbmlImport;
[...]
SIMExporterEbmlImport.MyClass obj = new SIMExporterEbmlImport.MyClass();
How do I go about ensuring:
You can probably tell by the question that I am not a professional C# developer, but trying to understand just enough to make this work. But as a consequence, if there is a simpler/more elegant solution to this issue, by all means please suggest it.
Upvotes: 0
Views: 129
Reputation: 305
A very helpful (much more C-literate) colleague helped me find an answer, without my previous hacky workaround:
// This field goes in one of my classes:
public static bool isAssemblyResolveRegistered = false;
// This code goes just before my method that needs to use the class in my assembly that
// I know won't be preloaded, but needs loading from a fixed location:
if (!isAssemblyResolveRegistered)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolve);
isAssemblyResolveRegistered = true;
}
private static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{ // This is an event handler for catching missing assemblies at runtime - designed to find and load the SIMExporterEbmlImport assembly and its dependencies
// Assume a fixed path for where the assembly is located (can update this later to look in multiple versions if needed)
// Should also add a switch block to only look for expected dependencies in this location,
// and throw a helpful error if some unexpected dependency is missing.
string dependentAssemblyName = new AssemblyName(args.Name).Name;
string dependentAssemblyLocation = "C:\\ProgramData\\EB Bridging Tools\\SimExporter\\" + dependentAssemblyName + ".dll";
// Try to load (will end up back here if lower dependencies are not met)
try
{
return Assembly.LoadFile(dependentAssemblyLocation);
}
catch
{
return null;
}
}
That means that I always explicitly handle unloaded dependencies at runtime, and can even supply multiple search paths if I ever need to (for different, but equally compatible, versions, for example).
My only residual issue (may open a separate question for this) is how to elegantly abort all execution with a user dialog if the DLLs are simply not present on the runtime machine.
Upvotes: 0