Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unload Assembly From App Domain

Code should create domain, load dll into domain, unload dll

But dll is still there after calling unload on new domain?

 private void Method1()
 {
        //create new domain
        AppDomain domain = AppDomain.CreateDomain("MyDomain");
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

        //load dll into new domain
        AssemblyName assemblyName = new AssemblyName();
        assemblyName.CodeBase = "c:\\mycode.dll";
        Assembly assembly = domain.Load(assemblyName);         

        //do work with dll
        //...

        //unload dll
        AppDomain.Unload(domain); 

        //still showing dll below ?????
        Assembly[] aAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string[] tokens = args.Name.Split(",".ToCharArray());
    System.Diagnostics.Debug.WriteLine("Resolving : " + args.Name);
    return Assembly.LoadFile(Path.Combine(new string[] { "c:\\", tokens[0] + ".dll" }));
}

Any ideas why dll is not unloading?

EDIT (have got it to work as below)

As Jean pointed out domain.Load was the problem, using CreateInstanceAndUnwrap with a proxy class in same project works.)

instead of

    //load dll into new domain *** this does not work
    AssemblyName assemblyName = new AssemblyName();
    assemblyName.CodeBase = "c:\\mycode.dll";
    Assembly assembly = domain.Load(assemblyName); 

to this

    // loads proxy class into new domain               
    Type myType = typeof(Proxy);
    var value = (Proxy)domain.CreateInstanceAndUnwrap(
             myType.Assembly.FullName,
             myType.FullName);   
    //DoWork:- loads assembly into domain
    // calls methods, returns result                 
    Int32 result = value.DoWork(pathToDll);
    //Unload domain and thus assembly
    AppDomain.Unload(domain);
    //Assembly not present in current domain
    Assembly[] list = AppDomain.CurrentDomain.GetAssemblies();

with below class added to current namespace

    public class Proxy : MarshalByRefObject
    {
        public Int32 DoWork(string assemblyPath)
        {
            try
            {
            Assembly assembly = Assembly.LoadFile(assemblyPath);
            Int32 response = 0;

            Type tObject = assembly.GetType("namespace.class");
            MethodInfo Method = tObject.GetMethod("method");

            Type myType = typeof(Proxy);
            object myInstance = Activator.CreateInstance(myType);                
            response =  (Int32) Method.Invoke(myInstance, null);

            return response;
            }
            catch (Exception ex)
            {
            throw ex;
            }
        }
    }
like image 534
Dere_2929 Avatar asked Oct 20 '22 20:10

Dere_2929


1 Answers

As a rule of thumb, as soon as you have an Assembly instance, it means that the assembly in question is loaded in the current domain.

Meaning that, when you call the AppDomain.Load method, you load the assembly both in your current domain, and in the new domain. (As you can see in the remarks for that method on MSDN, "This method should be used only to load an assembly into the current application domain.")

EDIT: The previously posted "solution" was removed as it did not actually solve the issue. A working solution was edited into the question by the author.

like image 130
Jean Hominal Avatar answered Nov 04 '22 21:11

Jean Hominal