2016-04-29 98 views
2

我想在運行時.dll加載到我自己的C#程序作爲一個插件。如果有新的更新卸載現有的插件DLL(InvokeHelper.dll)和下載更新的.dllInvokeHelper.dll)並將其加載到程序中而不終止進程(我的應用程序)。我閱讀了這些文章以完成這些任務(MSDN,Article2)但是,此代碼仍然無法動態卸載.dllC#後期綁定卸載DLL的

當我看着附加的DLL通過進程資源管理器附加的DLL不卸載。它存在於process explorer 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;    
      } 
     } 
    } 

enter image description here

+0

什麼是錯誤和堆棧跟蹤? – CathalMF

+0

@CathalMF'System.Reflection.TargetInvocationException'這是現在好了,我可以管理這個錯誤。(問題更新)但是,卸載成功,它應該可以rename.But不能這樣做。 – Elshan

+0

@devopsEMK你能在進程管理器中看到你創建的'AppDomain'嗎? –

回答

2

的問題是,您加載在單獨的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();