从 AppDomain 卸载 .DLL 需要帮助 - 即使使用 ShadowCopy 仍无法正常工作
Posted
技术标签:
【中文标题】从 AppDomain 卸载 .DLL 需要帮助 - 即使使用 ShadowCopy 仍无法正常工作【英文标题】:Help needed with unloading .DLL's from AppDomain - Still not working even with ShadowCopy 【发布时间】:2011-02-17 21:06:11 【问题描述】:我正在尝试执行以下操作。应用 A 是“母应用”。它保持打开状态。 App B 只是一个 .DLL,我在其中编写了一些从 App A 中指定的接口派生的类。
然后,从 App A 中,我将从 App B 中“导入”类并在其中运行方法。我希望能够动态更改 App B(更改代码并重新编译)并在 App A 中使用新代码。
我在 App B 中有一个后编译命令,它将新的 .DLL 复制到 App A 目录。应用 A 创建一个新的 AppDomain 并使用 ShadowCopying。我认为这已经足够了,但是当我尝试重新编译和复制 App B 的新 .DLL 时,它说该文件正在使用中并且无法被覆盖。
这是我现在拥有的代码:
App A(代码中的TestServer):
namespace TestServer
public interface IRunnable
void Run();
class Program
static void Main(string[] args)
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "DemoApp";
setup.ApplicationBase = Environment.CurrentDirectory;
setup.ShadowCopyDirectories = Environment.CurrentDirectory;
setup.ShadowCopyFiles = "true";
int _domain = 1;
while (true)
string typeName = Console.ReadLine();
AppDomain appDomain = AppDomain.CreateDomain("DemoDomain" + _domain, null, setup);
IRunnable runner = appDomain.CreateInstanceFromAndUnwrap("TestClient.dll", typeName) as IRunnable;
runner.Run();
AppDomain.Unload(appDomain);
_domain++;
App B(代码中的TestClient):
namespace TestClient
public class TestRunner : TestServer.IRunnable
public void Run()
Console.WriteLine("RUNNING");
public class Bob : TestServer.IRunnable
public void Run()
Console.WriteLine("BOB");
我已经读到,如果您使用来自其他应用程序域的东西,这些应用程序域可以自动加载 .DLL 或类似的东西。在这种情况下,我担心使用接口会导致基础 AppDomain 加载 .DLL 从而将其锁定。
我该如何解决这个问题/有更好的设置吗??
注意:我已经更新了我的代码,它仍然产生相同的结果。
【问题讨论】:
这应该很有用:social.msdn.microsoft.com/Forums/en-US/clr/thread/… 好吧,我决定努力破解它,一劳永逸地解决这个问题。这个解决方案远非优雅,但它有效。基本上,每次我输入一个新名称时,我都会用不同的名称复制 dll,加载并使用它。最后,我尝试删除它们(如果它们没有被锁定)。暂时解决我的问题,直到我成为更好的程序员。 【参考方案1】:您的代码仍在母 AppDomain 中运行,因为您将程序集和类型拉入其中。任何代码都应该在生成的域中运行。我已经展示了一种在我的网站上设置类似内容的方法:A simple way to start your code in a different AppDomain
我不是 100% 确定这一点,但这肯定是你必须采取的一步
更新
就那里提出的解决方案而言,跑步者的实例化将发生在 DomainLifetimeHook 的继承者中。显示的基础结构确保 Start 和 Stop 方法在由 AppDomainExpander 类创建的 AppDomain 中运行。该 Expander 是创建新域的类,因此您的域设置应该放在域的 Create 方法中。
【讨论】:
我会检查你的链接并报告回来。干杯 我主要关心的是能否在 A 运行时编写一些代码,然后让 A 执行新代码。这适用于您的方法吗?如果不是,我是在尝试以正确的方式做到这一点,还是应该考虑其他事情? 我明白了。我会试试看。感谢flq的帮助!【参考方案2】:主要问题是你在哪里做:
Type type = assm.GetType("TestClient." + typeName);
这发生在 App A 的主 AppDomain 中,结果是主 AppDomain 锁定了 App B 的程序集 .dll
flq 对他的博客文章的回答中的链接应该对你有用。
【讨论】:
我已经更新了代码但没有成功。任何想法为什么?我不认为我在主 AppDomain 中调用了任何东西,但我显然可能弄错了。【参考方案3】:在您打开 ObjectHandle 后,该类型必须加载到主应用程序域中。要正常工作,需要对未解包的ObjectHandle进行操作。
【讨论】:
不,它没有。 Unwrap() 返回另一个 AppDomain 中对象的代理,因此不需要(必然)需要定义要加载到主 AppDomain 中的类型的程序集。以上是关于从 AppDomain 卸载 .DLL 需要帮助 - 即使使用 ShadowCopy 仍无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章