2009-01-08 51 views
16

我有一個奇怪的問題。 我想刪除已經加載的程序集(硬盤上的plugin.dll),但程序集被操作系統(vista)鎖定,即使我已經卸載它。如何刪除AppDomain.Unload(域)後的pluginassembly

f.e.

AppDomainSetup setup = new AppDomainSetup(); 
setup.ShadowCopyFiles = "true"; 
AppDomain appDomain = AppDomain.CreateDomain(assemblyName + "_AppDomain", AppDomain.CurrentDomain.Evidence, setup); 
IPlugin plugin = (IPlugin)appDomain.CreateInstanceFromAndUnwrap(assemblyName,      "Plugin.MyPlugins"); 

我還需要assemblyinfos,因爲我不知道是哪個班的pluginassembly實現了IPlugin接口。應該可以在一個Pluginassembly中有多個插件。

Assembly assembly = appDomain.Load(assemblyName); 
if (assembly != null) { 
    Type[] assemblyTypes = assembly.GetTypes(); 
    foreach (Type assemblyTyp in assemblyTypes) { 
     if (typeof(IPlugin).IsAssignableFrom(assemblyTyp)) { 
     IPlugin plugin = (IPlugin)Activator.CreateInstance(assemblyTyp); 
     plugin.AssemblyName = assemblyNameWithEx; 
     plugin.Host = this; 
     } 
    } 
} 
AppDomain.Unload(appDomain); 

如何在不鎖定程序集的情況下從appDomain獲取assemblyinfos?

最好的問候

回答

20

我想我已經得到了答案! 如果您想刪除已加載的程序集,ØyvindSkaar的答案將不起作用。

,而不是

using (FileStream dll = File.OpenRead(path)) 
{ 
    fileContent = new byte[dll.Length]; 
    dll.Read(fileContent, 0, (int)dll.Length); 
} 
Assembly assembly = appDomain.Load(fileContent); 

,你必須使用

byte[] b = File.ReadAllBytes(assemblyName); 
assembly = Assembly.Load(b); 

問候

+1

當我嘗試它時,它工作正常,但是您的程序無論如何都是短的;) – 2009-01-12 18:13:39

3

我們做什麼,是有一個文件夾被監視組件。添加程序集時,應用程序將其複製到臨時目錄中,爲其提供唯一的文件名並從該目錄加載它。

當應用程序第一次加載時,它會嘗試清除臨時目錄。

我不認爲這直接回答你的問題,但它可能解決你的問題。

+0

+1影子副本 – 2009-07-03 18:04:08

3

如果將程序集作爲流加載,它應該可以工作。

byte[] fileContent; 
string path = "../../../test/bin/Debug/test.dll"; //Path to plugin assembly 
using (FileStream dll = File.OpenRead(path)) 
{ 
    fileContent = new byte[dll.Length]; 
    dll.Read(fileContent, 0, (int)dll.Length); 
} 
Assembly assembly = appDomain.Load(fileContent); 
File.Delete(path); 
+0

它應該,但它沒有。 :( 在File.Delete(路徑)UnauthorizedAccessException; – Ase 2009-01-12 10:30:01

+0

如果您不首先加載程序集,您可以刪除該文件嗎? – 2009-01-12 18:12:18

8

我知道這個線程是相當死了,但我目前正在就這個問題和我剛剛得到了回答(at 1h30 AM ...)

AppDomainSetup setup = new AppDomainSetup(); 
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; 
AppDomain app = AppDomain.CreateDomain("YaCsi", null, setup); 
app.DoCallBack(LoaderCallback); 
AppDomain.Unload(app); 
File.Delete("__YaCsi_Test01.dll"); 

static void LoaderCallback() 
{ 
    byte[] raw = File.ReadAllBytes("__YaCsi_Test01.dll"); 
    Assembly yacsi = Assembly.Load(raw); 
    ((IScript)yacsi.CreateInstance("Script")).Go(); 
} 

它實際上不會拋出任何異常! 希望有人會讀這個,它會回答這個問題!

4

看到這些網頁:

設置新AppDomain AppDomainSetupLoaderOptimization.MultiDomainHost

例如

domainnew = AppDomain.CreateDomain(newdomain_name, null, new AppDomainSetup { 
     ApplicationName = newdomain_name, 
     ApplicationBase = assembly_directory, 
     ConfigurationFile = ConfigurationManager.OpenExeConfiguration(assemblylocation).FilePath, 
     LoaderOptimization = LoaderOptimization.MultiDomainHost, 
     ShadowCopyFiles = shadowcopy ? "true" : "false", 
    } 
);