8

I am trying to implement dynamic loading of certain assemblies based on Environment.Is64BitProcess.
This basically works like this:

  • Register an event handler for the AppDomain.AssemblyResolve event
  • In the event handler load the assembly from the CPU type dependent sub path:

    private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
    {
        // args.Name is the display name of an assembly, e.g.:
        // MyAssembly, Version=5.0.0.0, Culture=neutral, PublicKeyToken=abcdefghijklmn
        if(!args.Name.Contains("MyAssembly"))
            return null;
    
        var path = Path.Combine(GetCpuTypeDependentPath(), "MyAssembly.dll");
        return Assembly.LoadFrom(path);
    }
    

Now, this has the problem, that it doesn't check for the version, publicKeyToken etc of the loaded assembly.
What I would like to do now is to call Assembly.Load and simply supply an additional probing path. I know that this doesn't work as there is no such overload. Is there some other way to achieve my goal?

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • [Does this help?](http://stackoverflow.com/questions/1373100/how-to-add-folder-to-assembly-search-path-at-runtime-in-net) Similar solution to yours, but doesn't appear to care about the version number / token. [This might be worth reading too.](http://www.codeguru.com/cpp/w-p/dll/article.php/c99/Application-Specific-Paths-for-DLL-Loading.htm) – Adam Houldsworth Aug 07 '12 at 14:24
  • @AdamHouldsworth: Thanks for the comment, but the first link has exactly the same problem: It doesn't care for version etc. The second link is for unmanaged DLLs, I don't think this applies here. – Daniel Hilgarth Aug 07 '12 at 14:32
  • Actually the CLR does the same (if not, very similar) checks for managed DLLs. Checks bin, gac, path, and some other places so as a workaround you can always place a new value in PATH just to see if that works. I take it not checking the version is a problem because you want to pick a specific version? – Adam Houldsworth Aug 07 '12 at 14:34
  • @AdamHouldsworth: Setting the PATH environment variable doesn't help. I want the version to be checked so that the loading failes if an assembly with a different version exists in the folder. – Daniel Hilgarth Aug 07 '12 at 14:43
  • Are you aware of Assembly Fusion API? (http://msdn.microsoft.com/en-us/library/aa964725) and especially CompareAssemblyIdentity. Would that help you? – Simon Mourier Aug 07 '12 at 16:21
  • @SimonMourier: Thanks for the hint, I wasn't aware of this API. But it looks a little bit like overkill :-) – Daniel Hilgarth Aug 07 '12 at 16:31

2 Answers2

2

Just compare the properties of the assembly you found with the one that was requested. For example, a version check could look like this:

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
    var name = new AssemblyName(args.Name);
    string path = System.IO.Path.Combine(IntPtr.Size == 8 ? "x64" : "x86", name.Name + ".dll");
    path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), path);
    var asm = Assembly.LoadFrom(path);
    var found = new AssemblyName(asm.FullName);
    if (name.Version != found.Version) throw new System.IO.FileNotFoundException(name.FullName);
    return asm;
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • And what about culture, architecture and public key token? Furthermore, this would lead to the assemblies being loaded into my AppDomain, even if it is the wrong one. – Daniel Hilgarth Aug 08 '12 at 05:32
  • Erm, what about them? Culture is always neutral since this is about code, architecture can't be wrong or it wouldn't load, .NET doesn't check the strong name either. Add the code if it makes you feel better, you don't need my help. Why you worry about the AppDomain when you detect such a gross problem is unclear. Don't catch that exception. – Hans Passant Aug 08 '12 at 08:36
  • I don't think that .NET doesn't check the strong name. If that would be the case, strong naming would be kinda useless... – Daniel Hilgarth Aug 08 '12 at 10:56
  • It does, "true" is the default: http://msdn.microsoft.com/en-us/library/cc679069(v=vs.90).aspx – Hans Passant Aug 08 '12 at 11:25
1

Short of probing assemblies yourself I don't see that you can do this. You'd only have to fire up another AppDomain that will search for matching assembly, so that you can unload assemblies loaded during probing. Unfortunately

Nikola Radosavljević
  • 6,871
  • 32
  • 44