Question

I am following Method 3 in http://support.microsoft.com/kb/837908 to load assemblies dynamically in C#. However, the code is not working for me. In the following section of the code, the author loads the missing assembly only if the name of missing assembly is one of the assemblies referenced by the application.

When I run this under debug, the function is getting called, but the missing assembly is not in any of those referenced assemblies, and so it is not set in my case. Any ideas why is this occurring? I am not sure if that DLL is C# or native C++. Could this be because C++ dlls cannot be loaded this way? Then, why is this function getting invoked for a missing C++ assembly? Any explanations appreciated. If this doesn't work for C++ assemblies referenced from C#, what are alternatives?

private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args)
{
    //This handler is called only when the common language runtime tries to bind to the assembly and fails.

    //Retrieve the list of referenced assemblies in an array of AssemblyName.
    Assembly MyAssembly,objExecutingAssemblies;
    string strTempAssmbPath="";

    objExecutingAssemblies=Assembly.GetExecutingAssembly();
    AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies();

    //Loop through the array of referenced assembly names.
    foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
    {
        //Check for the assembly names that have raised the "AssemblyResolve" event.
        if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(","))==args.Name.Substring(0, args.Name.IndexOf(",")))
        {
            //Build the path of the assembly from where it has to be loaded.                
            strTempAssmbPath="C:\\Myassemblies\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
            break;
        }

    }
    //Load the assembly from the specified path.                    
    MyAssembly = Assembly.LoadFrom(strTempAssmbPath);                   

    //Return the loaded assembly.
    return MyAssembly;          
}
Was it helpful?

Solution

The term "assembly" does not mean just any DLL; it means a DLL created with and for .NET. It is also often called "managed code" which roughly means that you use the .NET garbage collector rather than a conventional C++ heap for managing memory. (I am simplifying. There are also "mixed mode assemblies" which do get resolved this way although they use a mix of managed and unmanaged code. And "managed" means quite a bit more than just memory management.)

It does not matter whether your referenced assembly is written in C++/CLI, or in C#. C++/CLI is often confused with C++, but it is actually another language with extra facilities to take advantage of the managed environment. If you compile something C++'ish with the /clr switch, it's C++/CLI rather than C++.

There are three gotchas with the referenced KB article that you need to understand.

  1. "Method 3" in the article does not take indirectly referenced assemblies into account. That is, assemblies referenced from assemblies referenced from your main assembly. This is probably biting you right now.

  2. The article fails to mention that it is critical that you do as little as possible in the body of the method that registers your handler, or the jitter will resolve some assemblies before your handler is registered - even if the code lines responsible for that are below the registration in the same method. This is because JIT compilation precedes execution.

  3. If you deal with C++/CLI code, odds are that you also need to load some unmanaged C++ DLLs that the former link against. It is done using the traditional Windows DLL search order and outside of your resolver. But this is not your problem as long as you see the handler entered for a particular DLL. A normal kind of C or C++ DLL that has nothing to do with .NET will not be seen in the handler at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top