C#在运行时后期绑定卸载Dll [英] C# Late Binding Unloading Dll in Runtime

查看:59
本文介绍了C#在运行时后期绑定卸载Dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在运行时将 .dll 作为插件加载到我自己的c#程序中.如果有新的更新,请卸载现有的插件dll( InvokeHelper.dll )并下载更新的 .dll ( InvokeHelper.dll ),然后将其加载到程序中,而无需终止进程.(我的应用程序).我阅读了这些文章以完成这些任务(

解决方案

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

 公共类代理:MarshalByRefObject{公共无效Run(){var assembly = AppDomain.CurrentDomain.Load(File.ReadAllBytes(@"C:\ Users \ Mkrtich_Mazmanyan \ Downloads \ ExBinder \ Exbinder \ bin \ Debug \ InvokeHelper.dll"));Type [] mytypes = assembly.GetTypes();BindingFlags标志=(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);foreach(mytypes中的t类型){MethodInfo [] mi = t.GetMethods(flags);//您可以更改此标志,并注释一些标志:)仅查看plublic或bla bla elshan对象obj = Activator.CreateInstance(t);foreach(mi中的MethodInfo m){如果(m.Name.Equals("PrintHello"))m.Invoke(obj,null);//我的功能名称:)您可以通过config:D进行设置}}}} 

调用部分为:

value.Run();

I want to load .dll into my own c# program in run-time as a plugin.If there's new update unload existing plugin dll (InvokeHelper.dll) and download the updated.dll (InvokeHelper.dll) and load it into the program without terminating the process.(my application). I read these articles to complete these task(MSDN, Article2) But still this code doesn't work for unloading .dll dynamically.

When I looked attached dll via process explorer attached dll is not unloaded.It's exist in process explorer dll list.I think if the dll unload success I want to manually rename the old dll and replace the new one.

InvokeHelper.dll Source:

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();
            }
        }
    }
}

Load Dll Function:

 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);
    }

Proxy Class

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

解决方案

The problem is that you are loading the assembly in your separate AppDomain and returning that Assembly through the proxy, so the same assembly is also loaded in your default AppDomain. I have moved your invoking logic into the proxy class and its worked.

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
            }
        }
    }
}

Invoking part would be:

value.Run();

这篇关于C#在运行时后期绑定卸载Dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆