aero
aero

Reputation: 262

.NET Reference dll from other location

I'm making a program depending on some DLLs included in a third party program. I'm not allowed to distribute these DLLs myself. The third party program must be installed for my program to work.

How can i make a reference to these DLLs? I know the exact location of them through a registry key set by the program.

I have tried to add the files in Project->References and set CopyLocal to false but when i start i then get a FileNotFoundException "Could not load file or assembly".

I have tried to add an event to AppDomain.CurrentDomain.AssemblyResolve and load the files there but the problem is that i get the exception before my program even starts. Even if i put a breakpoint on the first line the exception will be thrown before the breakpoint is hit.

Upvotes: 6

Views: 4874

Answers (2)

Hans Passant
Hans Passant

Reputation: 941455

Your app bombs because the JIT compiler is the first one that needs to load the assembly. You'll need to carefully avoid using types from the assembly in your Main() method. That's not hard to do, just write another Main method and give it an attribute that tells the jitter that it should never inline that method. Without the attribute it may still bomb in the Release build when the optimizer inlines the method. Like this:

using System;
using System.Runtime.CompilerServices;

class Program {
    static void Main(string[] args) {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        DelayedMain(args);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void DelayedMain(string[] args) {
        // etc..
    }


    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
        // etc...
    }
}

Before you commit doing it this way, do contact the vendor and ask for recommendations. There has to be an easier way to exercise your license rights. The GAC would be a common choice, maybe you just need to run gacutil on your dev machine.

Upvotes: 4

From C# 3.0 in a Nutshell, 3rd edition, by Joseph and Ben Albahari, p. 557-558:

Deploying Assemblies Outside the Base Folder

Sometimes you might choose to deploy assemblies to locations other than the application base directory [...] To make this work, you must assist the CLR in finding the assemblies outside the base folder. The easiest solution is to handle the AssemblyResolve event.

(We can ignore the fact that in your case, someone other than you is deploying the assemblies.)

Which you tried. But a very important clue follows somewhat later. Read the two code comments:

public static void Loader
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.AssemblyResolve += FindAssem;

        // We must switch to another class before attempting to use
        // any of the types in C:\ExtraAssemblies:
        Program.Go();
    }

    static Assembly FindAssem(object sender, ResolveEventArgs args)
    {
        string simpleName = new AssemblyName(args.Name).Name;
        string path = @"C:\ExtraAssemblies\" + simpleName + ".dll";

        if (!File.Exists(path)) return null;
        return Assembly.LoadFrom(path);
    }
}

public class Program
{
    public static void Go()
    {
        // Now we can reference types defined in C:\ExtraAssemblies
    }
}

As you see, the class where you resolve the external assemblies must not refer to any type from any of the external DLLs anywhere. If it did, code execution would stop way before your AssemblyResolve ever gets a chance to run.

Upvotes: 10

Related Questions