none
How to unload DLL files that are in use.

    Question

  • Hi, i wonder if its possible to unload a DLL file that i allready added in "References" in C#... and then if its possible to load it again after i unloaded it..
    Friday, April 14, 2006 2:44 PM

Answers

  • OK, I will explain one possible approach, assuming that your program once in a while wants to access the library, call a function from it and release it again.

    First of all, do not include the library that you want to have exchangeable in your application, otherwise it might get loaded and is fixed afterwards.

    Step by step:

    1. Create a class library that contains an interface only like this one:
    namespace IClassLibrary1
    {
     
    public interface IClass1
       
    {
         
    void DoSomething();
        }
    }

    2. Create another class library that contains the logic for the interface, like this:
    public class Class1 : IClass1
    {
     
    public void DoSomething()
      {
       
    Console.WriteLine("test");
      }
    }

    3. Create your application and include the library with the interface as a reference (not the other one). Make sure both class libraries are next to the executable application in the Debug or Release folder. Use a function like the following one to get an instance of your class:
    namespace ConsoleApplication1
    {
     
    class Program
     
    {
       
    static IClass1 GetIClass1(string filename)
        {
         
    Assembly classLibrary1 = null;
         
    using (FileStream fs = File.Open(filename, FileMode.Open))
          {
           
    using (MemoryStream ms = new MemoryStream())
            {
             
    byte[] buffer = new byte[1024];
             
    int read = 0;
             
    while ((read = fs.Read(buffer, 0, 1024))>0)
                ms.Write(buffer, 0, read);
              classLibrary1 =
    Assembly.Load(ms.ToArray());
            }
          }
         
    foreach (Type type in classLibrary1.GetExportedTypes())
          {
           
    if (type.GetInterface("IClass1") != null)
             
    return Activator.CreateInstance(type) as IClass1;
          }

         
    throw new Exception("no class found that implements interface IClass1");
        }

        static void Main(string[] args)
        {
         
    IClass1 class1 = GetIClass1("ClassLibrary1.dll");
          class1.DoSomething();
        }
      }
    }


    The assembly is never directly loaded, the filestream the raw assembly was loaded from is closed, so even while you still hold the instance of the class you could replace the dll. Although, I would make sure that you never have two classes loaded at different points in time active at the same time. If you know the exact name of the class, you could also get rid of the iteration through all the exported classes and directly create the instance by the class name.

    Saturday, April 15, 2006 12:44 AM
  • yes, I let the code run once, so it works. What you describe there is possible and actually the code above does exactly what you want. The only additional thing I added was the interface.

    Just to explain the "concept" a little bit more in detail:

    You need one DLL "IClass1Library" which contains only the interface describing how to call your class, in the example interface "IClass1". Build this library "IClass1Library.dll" and leave it.

    Next you build your real DLL "Class1Library", add the "IClass1Library" as a reference to that project and implement that interface in class "Class1". Build this library "Class1Library.dll" and leave it.

    Next build your console application and add "IClass1Library" (NOT "Class1Library") as a reference to your project and use the code above to load the DLL that implements the class.

    So you will end up with 3 projects, the interface DLL, the class DLL and the application itself. The interface is necessary so that you know how to use your class, but because you go through the interface and do not link the class DLL to the application it is as loosely bound as possible and can be replaced even during runtime of the console application.

     

    There are even ways to get rid of the interface if you really need that, but try to get this to work first ;)

    Wednesday, April 19, 2006 6:57 PM
  • As I said already earlier ... you cannot use Assembly.Load and load from a file otherwise the assembly will be locked latest when you create a class instance from that assembly. You have to load the file into memory first, so that there is no direct connection to the assembly file. And to call a method on a class, you have to create the class instance first:

    class Program

    {

    static void Main(string[] args)

    {

    string filename = "ClassLibrary1.dll";

    Assembly library = null;

    object libraryInstance = null;

    // load assembly

    using (FileStream fs = File.Open(filename, FileMode.Open))

    {

    using (MemoryStream ms = new MemoryStream())

    {

    byte[] buffer = new byte[1024];

    int read = 0;

    while ((read = fs.Read(buffer, 0, 1024)) > 0)

    ms.Write(buffer, 0, read);

    library = Assembly.Load(ms.ToArray());

    }

    }

    foreach (Type type in library.GetExportedTypes())

    {

    if (type.Name.EndsWith("Class1"))

    libraryInstance = Activator.CreateInstance(type);

    }

     

    MethodInfo methodInfo = libraryInstance.GetType().GetMethod("Test3");

    methodInfo.Invoke(libraryInstance, new object[] {"firstname", "lastname"});

    }

    }

    Thursday, April 27, 2006 3:13 PM

All replies

  • It is possible if you change the way you load the DLL. If you do not link the DLL you want to use statically to the application, but instead load the types e.g. by the fully qualified name, the application is forced to lookup the assembly. You can handle this event to load the DLL. Instead of loading it directly then via Assembly.LoadFrom or so, you load the assembly file into a byte array first and load the assembly from the byte array. The DLL file itself is "free" after loading it like this and can even be exchanged or deleted (don't know about the effects ;) - guess that depends on your application).
    Take a look at the AppDomain.AssemblyResolve event.

     

    Another way is, if you dynamically create application domains and load and use the types of the DLLs in there and after being finished with the task, you dismiss the whole application domain, that frees the DLLs, too.

    Friday, April 14, 2006 2:58 PM
  • The assembly will only be completely unloaded if the manually created AppDomain is the only domain that accessed the assembly.  This means the only code in the manually created AppDomain is the only code that directly accesses anything in the assembly you want to unload.  Create a type reference or object reference to anything in that assembly in the main AppDomain means that assembly must be loaded into that AppDomain and unloading the manually created AppDomain will not unload that assembly from memory.
    Friday, April 14, 2006 4:09 PM
    Moderator
  • Didn't realy understand what you said. Im new in this area. This is the scenario. I have a program that use some methods in a DLL file, and i want to unload the DLL file so i can replace it. Like a update while the program is running, and then i want to load the same DLL file again. Is that possible? Or must i stop the program and then replace the DLL file.

    Thanks for helping //Mario

    Friday, April 14, 2006 9:57 PM
  • OK, I will explain one possible approach, assuming that your program once in a while wants to access the library, call a function from it and release it again.

    First of all, do not include the library that you want to have exchangeable in your application, otherwise it might get loaded and is fixed afterwards.

    Step by step:

    1. Create a class library that contains an interface only like this one:
    namespace IClassLibrary1
    {
     
    public interface IClass1
       
    {
         
    void DoSomething();
        }
    }

    2. Create another class library that contains the logic for the interface, like this:
    public class Class1 : IClass1
    {
     
    public void DoSomething()
      {
       
    Console.WriteLine("test");
      }
    }

    3. Create your application and include the library with the interface as a reference (not the other one). Make sure both class libraries are next to the executable application in the Debug or Release folder. Use a function like the following one to get an instance of your class:
    namespace ConsoleApplication1
    {
     
    class Program
     
    {
       
    static IClass1 GetIClass1(string filename)
        {
         
    Assembly classLibrary1 = null;
         
    using (FileStream fs = File.Open(filename, FileMode.Open))
          {
           
    using (MemoryStream ms = new MemoryStream())
            {
             
    byte[] buffer = new byte[1024];
             
    int read = 0;
             
    while ((read = fs.Read(buffer, 0, 1024))>0)
                ms.Write(buffer, 0, read);
              classLibrary1 =
    Assembly.Load(ms.ToArray());
            }
          }
         
    foreach (Type type in classLibrary1.GetExportedTypes())
          {
           
    if (type.GetInterface("IClass1") != null)
             
    return Activator.CreateInstance(type) as IClass1;
          }

         
    throw new Exception("no class found that implements interface IClass1");
        }

        static void Main(string[] args)
        {
         
    IClass1 class1 = GetIClass1("ClassLibrary1.dll");
          class1.DoSomething();
        }
      }
    }


    The assembly is never directly loaded, the filestream the raw assembly was loaded from is closed, so even while you still hold the instance of the class you could replace the dll. Although, I would make sure that you never have two classes loaded at different points in time active at the same time. If you know the exact name of the class, you could also get rid of the iteration through all the exported classes and directly create the instance by the class name.

    Saturday, April 15, 2006 12:44 AM
  • Im sure the code is right but still i couldn't get it work some how... i have to take a closer look on it, but if i still have some problem with it, could i contact you?..
    Sunday, April 16, 2006 9:37 AM
  • Just post here, and you will get an answer ;)
    Sunday, April 16, 2006 10:17 AM
  • Like i said before, i made a DLL file and after that i made a console program. I pasted everything that you wrote and it dosn't work. I got this error message:
    "The type or namespace name 'IClass1' could not be found (are you missing a using directive or an assembly reference?)". Have you tried your code?

    So, i edited it a little and tryied some of my ideas and it went more wrong than before. I lost myself somewhere in the code. However, you said something about that i had to add the reference, and that means that you have load the DLL when you debug the program. I don't want to have any connection with the DLL file what so ever at the begining, imagine yourself that you have the program on this location "C:\MyApp.exe" and then i want to load every DLL file that is in "C:\MyDLL\". So when i demand, the program will load the DLL Use the method WakeUp() and then after its done, unload it. Thats how i want it to work =) but im not sure it thats possible.  

    Thank you for helping me
    //Mario

    Wednesday, April 19, 2006 10:29 AM
  • yes, I let the code run once, so it works. What you describe there is possible and actually the code above does exactly what you want. The only additional thing I added was the interface.

    Just to explain the "concept" a little bit more in detail:

    You need one DLL "IClass1Library" which contains only the interface describing how to call your class, in the example interface "IClass1". Build this library "IClass1Library.dll" and leave it.

    Next you build your real DLL "Class1Library", add the "IClass1Library" as a reference to that project and implement that interface in class "Class1". Build this library "Class1Library.dll" and leave it.

    Next build your console application and add "IClass1Library" (NOT "Class1Library") as a reference to your project and use the code above to load the DLL that implements the class.

    So you will end up with 3 projects, the interface DLL, the class DLL and the application itself. The interface is necessary so that you know how to use your class, but because you go through the interface and do not link the class DLL to the application it is as loosely bound as possible and can be replaced even during runtime of the console application.

     

    There are even ways to get rid of the interface if you really need that, but try to get this to work first ;)

    Wednesday, April 19, 2006 6:57 PM
  • Thank you mate, it works now. =), no problem at all. While I was doing research on this i found out that i can use System.Reflection in other ways to. Like this code below.

    Assembly assembly = Assembly.LoadFrom("c:\\MyDLL.dll");

    string[] args = { "Name", "LastName" };

    foreach (Type type in assembly.GetTypes())

    {

    if (type.ToString().EndsWith(".Class1"))

    {

    foreach (MethodInfo methodInf in type.GetMethods())

    {

    if (methodInf.Name == "Test3") object ret = methodInf.Invoke(type, args);

    }

    }

    }

     

    But the only thing is that i can't use method Test3 somehow...Have to check it out more, thanks for everything =)

    //Mario

    Thursday, April 20, 2006 7:25 AM
  • Yip, Reflection can be fun ;) - that is what I meant to get rid of the interface, too.
    Thursday, April 20, 2006 3:04 PM
  • I give up, i have tried few stuffs but nothing worked, it was still attached to the dll, so how do you mean? How can i load a dll file like before without using Interface?
    Thursday, April 27, 2006 12:42 PM
  • As I said already earlier ... you cannot use Assembly.Load and load from a file otherwise the assembly will be locked latest when you create a class instance from that assembly. You have to load the file into memory first, so that there is no direct connection to the assembly file. And to call a method on a class, you have to create the class instance first:

    class Program

    {

    static void Main(string[] args)

    {

    string filename = "ClassLibrary1.dll";

    Assembly library = null;

    object libraryInstance = null;

    // load assembly

    using (FileStream fs = File.Open(filename, FileMode.Open))

    {

    using (MemoryStream ms = new MemoryStream())

    {

    byte[] buffer = new byte[1024];

    int read = 0;

    while ((read = fs.Read(buffer, 0, 1024)) > 0)

    ms.Write(buffer, 0, read);

    library = Assembly.Load(ms.ToArray());

    }

    }

    foreach (Type type in library.GetExportedTypes())

    {

    if (type.Name.EndsWith("Class1"))

    libraryInstance = Activator.CreateInstance(type);

    }

     

    MethodInfo methodInfo = libraryInstance.GetType().GetMethod("Test3");

    methodInfo.Invoke(libraryInstance, new object[] {"firstname", "lastname"});

    }

    }

    Thursday, April 27, 2006 3:13 PM
  • Thanks for this great code. I used this for an "Assembly Checker" library that I needed for my deployment automation. I needed a way to check if an Assembly (Either local or GAC) was compiled in Debug or Release mode prior to deploying it to our production servers from ClearCase. Your code snippet above helped me get past the problem I was fighting all day yesterday with the DLL being locked when I did an Assembly.LoadFrom or Assembly.LoadFile, even though I had tried setting up the ShadowCopy and creating a new Application Domain and then unloading it when it was done.

     

    Thanks again,

    Thursday, May 11, 2006 2:45 PM
  • This is very smart solution but unfortynatly it does not work when Class1 derives from ServicedComponet. The Assembly file gets locked during CreateInstance of Class1ignoring the assembly loaded from memory. Be so kind give me please some advise in this case if you know.

    Thank you.

    Wednesday, July 05, 2006 7:21 AM
  • I build a little test for that and in my opinion, if you used the whole thing above correctly, so not directly referencing the real type at all but just going through the loaded assembly - then you should not even be able to create an instance of the type.

    The problem with the enterprise service is that that the ServicedComponent seems to try to be "smart" and install/register itself. To do so it seems to need the physical assembly information which we stripped best we could. So at that step of CreateInstance it would bomb out with something like this:

    Unhandled Exception: System.EnterpriseServices.RegistrationException: The 'assembly' argument must be specified.
       at System.EnterpriseServices.RegistrationDriver.InstallAssembly(RegistrationConfig regConfig, Object obSync)
       at System.EnterpriseServices.RegistrationHelper.InstallAssemblyFromConfig(RegistrationConfig& regConfig)
       at System.EnterpriseServices.RegistrationHelper.InstallAssembly(String assembly, String& application, String partition, String& tlb, InstallationFlags installFlags)
       at System.EnterpriseServices.RegistrationHelper.System.EnterpriseServices.Thunk.IThunkInstallation.DefaultInstall(String asm)
       at System.EnterpriseServices.Thunk.Proxy.RegisterAssembly(Assembly assembly)
       at System.EnterpriseServices.Thunk.Proxy.LazyRegister(Guid id, Type serverType, Boolean checkCache)
       at System.EnterpriseServices.Thunk.Proxy.CoCreateObject(Type serverType, Boolean bQuerySCInfo, Boolean& bIsAnotherProcess, String& uri)
       at System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance(Type serverType)

     

    For what purpose do you try to use the code? Are you just trying to figure out information about the class? Then you can probably go along without instantiating it and just work through the type.

    If you want to use it, it depends pretty much on your application. Either you have to move the functionality you want to be in a dynamical loadable DLL into another DLL to separate it out or if it is something like a COM+ Server application you would just place it in the GAC, setup an idle unload time for the application and replace the version in the GAC for updates.

    Wednesday, July 05, 2006 3:29 PM
  • I just wanted to send everyone involved in this thread a quick thank you.

     

    I was having a similiar issue.  I was able to piece together the info I needed.

     

    Thanks much.  

    Sunday, June 17, 2007 5:22 PM
  • I have another question though, Do you mean to say that if the file is again loaded the previous loaded image will be unloaded ? the question here is how to Unload the Loaded assembly.
    Monday, July 02, 2007 6:04 PM
  • Well, that is a little bit misleading, though. Here are two ansers mixed up:

    1) How to load a DLL so that the DLL is not locked and can be replaced during runtime: For that just use th eloading method I posted before, so load the file first and load the assembly from the raw byte data, also cache the assembly and override AppDomain.ResolveAssembly to be safe. Loaded DLLs will not be unloaded, you can just replace the file and reload the new assembly.

    2) How to unload unload a DLL: For that you have to follow what Peter Ritchie said, create a new AppDomain, load the assembly into the new AppDomain and to unload destroy the AppDomain - make sure to not reference the assembly to unload directly from any other AppDomain or it will be loaded into that one, too, and therefore not be unloaded from the application.

    Tuesday, July 03, 2007 3:59 PM
  • Hi all!
    I was wondering how i can get rid of the interface like you said before. Is there a way to even update the interface at runtime? Or did you mean that its possible to call the at runtime introduced type directly (means without an interface)?

    Sunday, July 29, 2007 5:21 PM
  •  Tracecat wrote:
    Hi all!
    I was wondering how i can get rid of the interface like you said before. Is there a way to even update the interface at runtime? Or did you mean that its possible to call the at runtime introduced type directly (means without an interface)?

     

    Updating an interface like that during runtime does not make much sense to me, as at least one part should know what it uses, e.g. if you write an application that accepts plugins, the plugins should be coded against an interface so that the application knows how to call them.

    Although it is of course possible to not use an interface at all and just call the methods via reflection.

     

    e.g. if you know the type (careful with this code, I just write it in the forum here without having it checked in a compiler):

     

    Type type = ....;
    MethodInfo methodInfo = type.GetMethod("MyMethodName", BindingFlags.Public|BindignFlags.Instance);

    object typeInstance = Activator.CreateInstance(type);

    methodInfo.Invoke(typeInstance, object[] { "param1", "param2" } );

     

    Although reflection works to figure out whatever you want about a class and the methods and allows you to call them, programming something where you examine a class from an assembly and still not touching the assembly from the main application, so that the assembly can still be unloaded, might be rather difficult. If you truely want to unload the assembly, you have to examine and call it from a dynamically created AppDomain, too.

    Sunday, July 29, 2007 11:29 PM
  • Hey John!
    Thx for your answer. You`re right...updating only the the interface would`t make much sense for a plug in architecture. I´m currently programming on a code framework where you can hot deploy components(classes) at runtime. So there might be a situation where i change two components including the interface they are communicating over. But as you mentioned, if this would be the case i had to update not only the interface but the two components too....


    Thursday, August 09, 2007 4:41 PM
  • Can someone explain why this example wouldn't make sense for a plugin architechture?  We are doing this exact thing for our plugin architecture so that users can update the existing plugins without worry of them being locked.  Is there a better way to do that?  Also, we found that if you try to load an interface from an assembly by reading the assembly into memory, it fails in the case where the there is another assembly that is referenced, i.e. in the case where the object being created is actually a subclass of another class which is defined in a separate assembly.  However, using the CreateInstanceFrom(assemblyFile) works just fine.  Is there a way to solve this one? 

    Tuesday, September 18, 2007 9:45 PM
  •  

    @Can someone explain why this example wouldn't make sense for a plugin architechture?

     

    Only assuming that you don't know anything about the plugin does not make sense. If you design e.g. a plugin system for calculations, why would you go ahead and let anybody code plugins without any rules and then go through the hassle of somehow figuring out a generic way to call them? Instead you would just define an interface and tell the plugin coders to code a class against that interface, so that you know how to call the methods without reflection.

     

    @we found that if you try to load an interface from an assembly by reading the assembly into memory, it fails in the case where the there is another assembly that is referenced

     

    You can solve that if you know where the referenced assembly would be found. In that case hook to the AppDomain.CurrentDomain.ResolveType and AppDomain.CurrentDomain.ResolveAssembly events and disect the AssemblyQualifiedName passed into the event handler to figure out the filename of the assembly, load it and return it.

    Wednesday, September 19, 2007 4:54 PM
  •  

    >Only assuming that you don't know anything about the plugin does not make sense.

     

    Oh I see it now, I'm sorry I missed that part a couple posts ago where the question had changed to asking about replacing the interface on the fly as well. 

     

    >You can solve that if you know where the referenced assembly would be found. In that case hook to the AppDomain.CurrentDomain.ResolveType and AppDomain.CurrentDomain.ResolveAssembly events and disect the AssemblyQualifiedName passed into the event handler to figure out the filename of the assembly, load it and return it.

     

    Interesting...I will give that a try.  Thanks.

    Wednesday, September 19, 2007 5:47 PM
  • Hello. I am dynamically loading my assemblies as described in this thread. I'm trying to step into the method i'm invoking with no luck. Any sugggestions on how I might go about doing this?

    methodInfo.Invoke(libraryInstance, new object[] { ... params... }


    I even went ahead & put a call to: System.Diagnostics.Debug.Assert(false); in my method implementation & I get the debug assertion flagged but I still can't break into the code.

    All suggestions welcome!

    Thanks.
    Tuesday, November 13, 2007 4:58 PM
  •  

    Have you tried running your program standalone (not in VS), and then opening the file in VS and attaching to the running process?   I find that attaching to a running process more reliably gets me into dynamically invoked code.  Although for some reason i find that i have to put in two breakpoints instead of one.  not sure why two works where one doesn't, but sometimes you just go with what works......

    Wednesday, November 14, 2007 2:18 PM
  • Also, I should mention since I just ran into this, you need to have the .pdb file in the same directory as the dll you are dynamically loading. 

     

    Wednesday, December 12, 2007 4:25 PM
  • Thanks for this thread/answer. It is working for me.

    There is still a little problem.
    The memory allocated to load the DLL is not released until the program quit's. I tried to invoke it 10000 times while i watched the task manager. The allocated memory will increase for every invoke.

    Does anybody have a solution for that.

    Thanks Christian
    Thursday, February 26, 2009 12:29 AM
  • Did you ever resolve this memory issue? Is it still a problem?
    Sunday, October 04, 2009 6:30 AM
  • I have this same problem. If I dynamically load an assembly using Load(byte[]) then I cannot debug into that assembly even though the .pdb file for that dynamically loaded assembly is in the folder that the other assemblies are loaded from. Did you ever solve it? - Dave
    Sunday, October 04, 2009 6:32 AM
  • OK I figured it out - just use the other version of Load(byte[], byte[]) where the second byte array is the symbol stream!
    • Proposed as answer by CodeSlinger Sunday, October 04, 2009 7:06 AM
    Sunday, October 04, 2009 7:05 AM
  • Though it was quite late, still I feel that instead of getting the bytes from file in above mentioned mehtod, we can use, 

    byte[] byteArray= File.ReadAllBytes(strFileName);

    Assembly objAssem = Assembly.Load(byteArray);

    //Do Other Work

    FileInfo fInfo = new FileInfo(strFileName);

    if(fInfo.exists) fInfo.Delete();

    //I have personally checked that code and there will be no problem to delete the file.

     

    Monday, July 04, 2011 10:09 AM