繁体   English   中英

C# 后期绑定在运行时卸载 Dll

[英]C# Late Binding Unloading Dll in Runtime

我想加载.dll在运行时到我自己的C#程序作为一个插件。如果有现有的插件DLL(InvokeHelper.dll)新的更新卸载和下载更新的.dll (InvokeHelper.dll),并将其装入程序而不终止进程。(我的申请)。 我阅读了这些文章来完成这些任务( MSDN, Article2 )但是这段代码仍然不能用于动态卸载.dll

当我通过进程资源管理器查看附加的 dll 时,附加的 dll 没有卸载。它存在于进程资源管理器dll 列表中。我想如果 dll 卸载成功,我想手动重命名旧的 dll 并替换新的。

InvokeHelper.dll来源:

using System;

namespace InvokeHelper
{
    public class LateBindingInvokeHelper
    {
        public void PrintHello()
        {
            using (System.IO.StreamWriter w = new System.IO.StreamWriter(@"Invoker.txt", true))
            {
                w.WriteLine(DateTime.Now.ToString());
                w.Flush();
            }
        }
    }
}

加载DLL函数:

 private AppDomain domain = null;
 private void LoadDll()
        {
            AppDomainSetup domInfo = new AppDomainSetup();
            domInfo.ApplicationBase = System.Environment.CurrentDirectory;
            Evidence adevidence = AppDomain.CurrentDomain.Evidence;
            domInfo.DisallowBindingRedirects = false;
            domInfo.DisallowCodeDownload = true;
            domain = AppDomain.CreateDomain("MyDomain", adevidence , domInfo);

            Type type = typeof(Proxy);
            var value = (Proxy)domain.CreateInstanceAndUnwrap(
                type.Assembly.FullName,
                type.FullName);

            var assembly = value.GetAssembly(@"C:\dev\ExBinder\ExBinder\bin\Debug\InvokeHelper.dll");
            Type[] mytypes = assembly.GetTypes();
            BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
            foreach (Type t in mytypes)
            {
                MethodInfo[] mi = t.GetMethods(flags); // you can change this flag , commented some flags :) view only plublic or bla bla 
                Object obj = Activator.CreateInstance(t);
                foreach (MethodInfo m in mi)
                {
                    if (m.Name.Equals("PrintHello")) m.Invoke(obj, null); //my func name :) you can set this via config :D
                }
            }
        }

    private void button2_Click(object sender, EventArgs e)
    {
        LoadDll();
        AppDomain.Unload(domain);
    }

代理类

public class Proxy : MarshalByRefObject
    {
        public Assembly GetAssembly(string assemblyPath)
        {
            try
            {
                return Assembly.LoadFile(assemblyPath);
            }
            catch (Exception)
            {
                return null;               
            }
        }
    }

在此处输入图片说明

问题是您正在单独的 AppDomain 中加载程序集并通过代理返回该Assembly集,因此在您的默认 AppDomain 中也加载了相同的程序集。 我已将您的调用逻辑移到代理类中并且它起作用了。

public class Proxy : MarshalByRefObject
{
    public void Run()
    {
        var assembly = AppDomain.CurrentDomain.Load(File.ReadAllBytes(@"C:\Users\Mkrtich_Mazmanyan\Downloads\ExBinder\Exbinder\bin\Debug\InvokeHelper.dll"));

        Type[] mytypes = assembly.GetTypes();
        BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
        foreach (Type t in mytypes)
        {
            MethodInfo[] mi = t.GetMethods(flags); // you can change this flag , commented some flags :) view only plublic or bla bla elshan
            Object obj = Activator.CreateInstance(t);
            foreach (MethodInfo m in mi)
            {
                if (m.Name.Equals("PrintHello")) m.Invoke(obj, null); //my func name :) you can set this via config :D
            }
        }
    }
}

调用部分将是:

value.Run();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM