2008-09-23 69 views
38

我想知道如何卸载加载到主AppDomain中的程序集。如何从主AppDomain卸载程序集?

我有以下代码:

var assembly = Assembly.LoadFrom(FilePathHere); 

我需要/想能当我完成卸载该组件。

感谢您的帮助。

+1

尽量不要使用LoadFrom,它在与Load上下文不同的上下文中并可能导致问题。 – user7116 2008-09-24 01:09:32

+0

好问题,但我看不到任何关于如何解决的清晰答案var assembly = Assembly.LoadFrom(FilePathHere); – 2012-07-13 17:09:35

回答

32

您无法从应用程序域卸载程序集。您可以销毁AppDomain,但是一旦将程序集加载到AppDomain中,它就存在于AppDomain的生命周期中。

Why isn't there an Assembly.Unload method?

见杰森Zander的解释如果您使用的3.5,您可以使用外接程序框架,使其更易于管理/调用到不同的应用程序域(你可以卸载,卸载所有的组件) 。如果您之前使用的是版本,则需要自己创建一个新的AppDomain以卸载它。

+0

我以为这改变了.NET 3.5? – 2008-09-23 19:52:46

+1

有没有计划允许从应用程序域卸载程序集(我不希望他们要么,这是很难做的,那些关心将使用更安全和更清洁的解决方法)。你可以做的最好的是Khoth提到的轻量级代码生成 – ShuggyCoUk 2009-03-20 14:46:17

14

如果不卸载整个AppDomain,则无法卸载程序集。 Here's why

  1. 您正在运行的应用程序域代码。这意味着有潜在的呼叫站点和呼叫堆栈,其中有地址,期望继续工作。

  2. 假设您设法跟踪程序集的所有句柄和对已运行代码的引用。假设你没有编写代码,一旦你成功地释放了程序集,你只能释放元数据和IL。 JIT'd代码仍然在应用程序域加载器堆中分配(JIT'd方法按顺序在缓冲区中按调用顺序分配)。

  3. 最后一个问题涉及已加载共享的代码,否则更正式地称为“域中立”(在ngen工具上检出/共享)。在这种模式下,程序集的代码被生成,可以从任何应用程序域执行(没有硬连线)。

建议您围绕应用程序域边界自然设计应用程序,其中完全支持卸载。

4

如果您想要临时代码可以随后卸载,根据您的需要,DynamicMethod类可能会做你想做的。尽管如此,这并不能为你提供课程。

8

您应该在另一个AppDomain中加载临时程序集,如果不使用,则可以卸载AppDomain。它安全快速。

0

我知道它的旧的,但可能会帮助别人。您可以从流中加载文件并将其释放。它为我工作。我找到了解决方案HERE

希望它有帮助。

13

我也知道这是很旧的,但可能会帮助有这个问题的人! 这是我发现的一种方法! 而不是使用:

var assembly = Assembly.LoadFrom(FilePathHere); 

使用本:

var assembly = Assembly.Load(File.ReadAllBytes(FilePathHere)); 

这实际上加载该文件本身,而不是汇编文件的“内容”。这意味着组件文件上没有文件锁!所以现在它可以复制,删除或升级而不关闭你的应用程序或试图使用单独的AppDomain或Marshaling!

优惠价:非常容易修复1代码! CONS:无法使用AppDomain,Assembly.Location或Assembly.CodeBase。

现在你只需要销毁在程序集上创建的所有实例。 例如:

assembly = null; 
0

作为替代,如果组件只是装载在第一位置,以检查如公钥组件的信息,更好的方法是将不加载它,而检查信息通过首先加载AssemblyName:

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe"); 
byte[] publicKey = an.GetPublicKey(); 
CultureInfo culture = an.CultureInfo; 
Version version = an.Version;