2016-11-16 76 views
0

我正在嘗試檢查程序集的某些元數據而不將其永久加載到我的應用程序中。爲此,我創建一個臨時的​​AppDomain,將程序集加載到它中,然後卸載整個​​。根據this question的答案,這是「正確」的方式來做到這一點。AppDomain.Unload不會卸載程序集

但卸載程序集後,它仍然保留在當前AppDomain中。爲什麼?

this question的回答表明程序集可以被「放入」當前域,但我不明白我的例子中這怎麼可能。應用程序的其餘部分根本不使用程序集,甚至沒有被引用。即使在裝配後立即卸載sandobx,觀察到的行爲仍然存在。

This article表示域中立程序集不能以這種方式卸載。這是原因嗎?如果是的話,我可以以某種方式阻止大會被視爲領域中立?

private void Check() 
{ 
    string assemblyName = "SomeUnrelatedAssembly"; 
    var sandbox = AppDomain.CreateDomain("sandbox"); //create a discardable AppDomain 
    //load the assembly to the sandbox 
    byte[] arr; 
    using (var memoryStream = new MemoryStream()) 
    { 
     using (var fileStream = new FileStream($"{assemblyName}.dll", FileMode.Open)) 
      fileStream.CopyTo(memoryStream); 
     arr = memoryStream.ToArray(); 
    } 

    Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints false 
    sandbox.Load(arr); 

    //and unload it  
    AppDomain.Unload(sandbox);  
    Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints true! 
} 

private static bool IsAssemblyLoaded(string assemblyName) 
{ 
    return AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.Contains(assemblyName)); 
} 

EDIT:我已經檢查與處理資源管理器(如this)加載過程。加載的程序集不是域中立的。

+0

你可以告訴我們什麼'//檢查索姆e元數據代碼看起來像?儘管在沙盒域中加載程序集,但可能會通過當前域中的元數據。 –

+0

即使'sanbox.Load'和'AppDomain.Unload'指令之間沒有任何內容,行爲也是一樣的。 – tearvisus

回答

0

你是對的。你的程序集被認爲是域中立的,並跨應用程序域共享。

使用AppDomain.CreateDomain重載允許您提供設置信息:

信息:

AppDomainSetup info = new AppDomainSetup(); 
info.ApplicationBase = domainDir; 
info.ApplicationName = executableNameNoExe; 
info.LoaderOptimization = LoaderOptimization.SingleDomain; 

變化:

AppDomain.CreateDomain("sandbox"); 

要:

AppDomain.CreateDomain("sandbox",null, info); 
+0

不幸的是,它不起作用。第二個檢查仍然打印真實。 – tearvisus

+0

如果在「Check」調用之前調用'IsAssemblyLoaded()'會怎麼樣?可能是它早些時候被加載? –

+0

通過'第二次檢查'我的意思是第二次'IsAssemblyLoaded'調用。這個例子中的Check方法只被調用一次。 – tearvisus