我想在运行时将.dll
加载到我自己的c#程序中作为插件。如果有新的更新卸载现有的插件dll( InvokeHelper。 dll )并下载更新的.dll
( InvokeHelper.dll )并将其加载到程序中而不会终止该过程。(我的应用程序)。我阅读了这些文章来完成这些任务(MSDN, Article2)但是这段代码仍无法动态卸载.dll
。
当我通过进程资源管理器查看附加的dll时,附加的dll没有被卸载。它存在于process explorer 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;
}
}
}
答案 0 :(得分: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();