AppDomain.Unload不会释放我用Reflection加载的程序集

6 .net assemblies

可能重复:
如何在AppDomain.Unload(域)后删除pluginassembly

在临时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);
Run Code Online (Sandbox Code Playgroud)

无论如何,删除失败,因为文件仍然被锁定.它们不应该被释放因为我卸载了临时AppDomain吗?

Mat*_*els 9

我知道这是一个老问题,但仍然没有接受的答案.我偶然发现了这个问题寻找答案,因此我认为发布我在这里找到的解决方案可能会有用.

问题

tempAppDomain.Load(assemblyFileBuffer, symbolsFileBuffer);将程序集加载到tempAppDomain执行代码的app域中.您还必须卸载该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);
    }
}
Run Code Online (Sandbox Code Playgroud)

来源

http://msdn.microsoft.com/en-us/library/system.appdomain.docallback.aspx
http://msdn.microsoft.com/en-us/library/36az8x58.aspx
https://stackoverflow.com/一个/二十一万零三百三十六分之二百四十七万五千一百七十七

  • 这个答案帮助我解决了一个非常相似的目标.我唯一的问题是:我无法使用lambda作为回调工作负载.我创建了一个小助手类,扩展了[MarshalByRefObject](http://msdn.microsoft.com/en-us/library/system.marshalbyrefobject.aspx)来创建可序列化的跨appdomain对象,这也允许我从中获取一些结果. "远程"通话. (2认同)

小智 6

请参阅以下页面:

http://connect.microsoft.com/VisualStudio/feedback/details/536783/vsip-assembly-file-handles-not-being-released-after-appdomain-unload

http://msdn.microsoft.com/it-it/library/43wc4hhs.aspx

使用LoaderOptimization.MultiDomainHost设置新的AppDomain AppDomainSetup

例如

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",
    });
Run Code Online (Sandbox Code Playgroud)

最好的祝福


Dav*_*ith 4

如果您像这样阅读文件:

FileStream assemblyFileStream = new FileStream(tempAssemblyFile, FileMode.Open);

byte[] assemblyFileBuffer = new byte[assemblyFileStream.Length];
assemblyFileStream.Read(assemblyFileBuffer, 0, (int)assemblyFileStream.Length);
Run Code Online (Sandbox Code Playgroud)

如果您这样做,您的问题应该得到解决:

byte[] newAssemblyBuffer = new byte[assemblyFileBuffer.Length];
assemblyFileBuffer.CopyTo(newAssemblyBuffer, 0);
Run Code Online (Sandbox Code Playgroud)

并改变这个:

Assembly projectAssembly = tempAppDomain.Load(newAssemblyFileBuffer, symbolsFileBuffer);
Run Code Online (Sandbox Code Playgroud)

或者,这应该也可以工作并允许您跳过文件流:

byte[] assemblyFileBUffer = File.ReadAllBytes(tempAssemblyFile);
Run Code Online (Sandbox Code Playgroud)