2008-09-23 100 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;