how to delete the pluginassembly after AppDomain.Unload(domain)

爱⌒轻易说出口 提交于 2019-12-03 18:30:19

问题


i have a weird problem. i would like to delete an assembly(plugin.dll on harddisk) which is already loaded, but the assembly is locked by the operating system (vista), even if i have unloaded it.

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");

I also need the assemblyinfos, because I don't know which classes in the pluginassembly implements the IPlugin Interface. It should be possible to have more than one Plugin in one 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);

How is it possible to get the assemblyinfos from the appDomain without locking the assembly?

best regards


回答1:


I think i've the answer! the answer from Øyvind Skaar will not work, if you would like to delete the loaded assembly.

instead of

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

you have to use

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

best regards




回答2:


I know this thread is quite dead, but I am currently working on this and I just got the answer (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();
}

And it actually don't throw any exceptions!!! Hope someone will read this and that it will answer there question!




回答3:


If you load the assembly as a stream, it should work.

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);



回答4:


See these pages:

  • 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

Set a new AppDomain AppDomainSetup with LoaderOptimization.MultiDomainHost

E.g.

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",
    }
);



回答5:


What we do, is to have one folder that is watched for assemblies. When an assembly is added, the application copies it to a temp directory gives it a unique file name and loads it from there.

When the application is first loaded, it tries to clear out the temp directory.

I don't think that directly answers your question, but it probably solves your problem.



来源:https://stackoverflow.com/questions/425077/how-to-delete-the-pluginassembly-after-appdomain-unloaddomain

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!