可能重复:
how to delete the pluginassembly after AppDomain.Unload(domain)
在临时AppDomain中加载程序集以读取其GetUsedReferences属性时,我遇到了一个问题。一旦我这样做,我调用AppDomain.Unload(tempDomain)然后我尝试通过删除文件来清理我的混乱。因为文件被锁定而失败。我虽然卸载了临时域名!任何想法或建议都会受到高度赞赏。以下是我的一些代码:
//I already have btyes for the .dll and the .pdb from the actual files
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = Environment.CurrentDirectory;
domainSetup.ShadowCopyFiles = "true";
domainSetup.CachePath = Environment.CurrentDirectory;
AppDomain tempAppDomain = AppDomain.CreateDomain("TempAppDomain", AppDomain.CurrentDomain.Evidence, domainSetup);
//Load up the temp assembly and do stuff
Assembly projectAssembly = tempAppDomain.Load(assemblyFileBuffer, symbolsFileBuffer);
//Then I'm trying to clean up
AppDomain.Unload(tempAppDomain);
tempAppDomain = null;
File.Delete(tempAssemblyFile); //I even try to force GC
File.Delete(tempSymbolsFile);
无论如何,删除失败,因为文件仍然被锁定。它们不应该被释放,因为我卸载了临时AppDomain吗?
答案 0 :(得分:9)
我知道这是一个老问题,但仍然没有接受的答案。我偶然发现了这个问题寻找答案,因此我认为发布我在这里找到的解决方案可能会有用。
tempAppDomain.Load(assemblyFileBuffer, symbolsFileBuffer);
会将程序集加载到tempAppDomain
,但也会加载到执行代码的应用程序域中。您还必须卸载该app域以便能够删除该文件。你可能不想这样做。
您必须执行从应用程序域tempAppDomain
加载程序集的代码。您可以使用DoCallBack
上的tempAppDomain
函数执行tempAppDomain
中的代码。如果您在那里加载程序集,那么您应该可以在调用tempAppDomain.Unload()
后删除该文件。
class Program
{
private static string assemblyPath = @"C:\Users\wesselm\Documents\Visual Studio 2010\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\ClassLibrary1.dll";
static void Main(string[] args)
{
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
var appDomain = AppDomain.CreateDomain("myAppDomain", null, setup);
// Loads assembly in both application domains.
appDomain.Load(AssemblyName.GetAssemblyName(assemblyPath));
// Only loads assembly in one application domain.
appDomain.DoCallBack(() => AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(assemblyPath)));
AppDomain.Unload(appDomain);
File.Delete(assemblyPath);
}
}
http://msdn.microsoft.com/en-us/library/system.appdomain.docallback.aspx
http://msdn.microsoft.com/en-us/library/36az8x58.aspx
https://stackoverflow.com/a/2475177/210336
答案 1 :(得分:6)
请参阅以下页面:
http://msdn.microsoft.com/it-it/library/43wc4hhs.aspx
使用LoaderOptimization.MultiDomainHost设置新的AppDomain AppDomainSetup
E.g。
domainnew = AppDomain.CreateDomain(
newdomain_name,
null,
new AppDomainSetup
{
ApplicationName = newdomain_name,
ApplicationBase = assembly_directory,
ConfigurationFile = ConfigurationManager.OpenExeConfiguration(assemblylocation).FilePath,
LoaderOptimization = LoaderOptimization.MultiDomainHost,
//http://msdn.microsoft.com/it-it/library/43wc4hhs.aspx
ShadowCopyFiles = shadowcopy ? "true" : "false",
});
最好的问候
答案 2 :(得分:3)
如果您正在阅读这样的文件:
FileStream assemblyFileStream = new FileStream(tempAssemblyFile, FileMode.Open);
byte[] assemblyFileBuffer = new byte[assemblyFileStream.Length];
assemblyFileStream.Read(assemblyFileBuffer, 0, (int)assemblyFileStream.Length);
如果你这样做,你的问题应该解决:
byte[] newAssemblyBuffer = new byte[assemblyFileBuffer.Length];
assemblyFileBuffer.CopyTo(newAssemblyBuffer, 0);
并改变这一点:
Assembly projectAssembly = tempAppDomain.Load(newAssemblyFileBuffer, symbolsFileBuffer);
或者这应该也可以,并允许您跳过文件流:
byte[] assemblyFileBUffer = File.ReadAllBytes(tempAssemblyFile);
答案 3 :(得分:3)
您必须使用Wrapper才能成功卸载AppDomain。 在这里你可以找到一个很好的例子 - http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm