2009-01-08 6 views
16

tengo un problema extraño. me gustaría eliminar un ensamblado (plugin.dll en el disco duro) que ya está cargado, pero el ensamblado está bloqueado por el sistema operativo (vista), incluso si lo he descargado.cómo eliminar el pluginassembly después de AppDomain.Unload (dominio)

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

también necesito los assemblyinfos, porque no sé qué clases en el pluginassembly implementa la interfaz IPlugin. Debería ser posible tener más de un Complemento en un PlugInsamblador.

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

¿Cómo es posible obtener el assemblyinfos del dominio de la aplicación sin bloquear el conjunto?

mejores deseos

Respuesta

20

Creo que tengo la respuesta! la respuesta de Øyvind Skaar no funcionará, si desea eliminar el conjunto cargado.

en lugar de

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

que tienen que utilizar

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

mejores deseos

+1

Funcionó bien cuando lo probé, pero el suyo es más corto de todos modos;) –

+0

Hay un montón de preguntas similares sobre la descarga de archivos DLL y el uso de AppDomains por separado, pero no parecen funcionar cuando realmente desea * eliminar * la DLL. Esto definitivamente hace el truco sin importar :) – Jedidja

+0

¡Agradable! Ni siquiera necesita otro dominio de aplicación. –

3

Lo que hacemos, es tener una carpeta que se observó durante las asambleas. Cuando se agrega un ensamblaje, la aplicación lo copia a un directorio temporal, le da un nombre de archivo único y lo carga desde allí.

Cuando la aplicación se carga por primera vez, intenta borrar el directorio temporal.

No creo que responda directamente su pregunta, pero probablemente resuelva su problema.

+0

+1 para las instantáneas –

3

Si carga el conjunto como una secuencia, debería funcionar.

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

debería, pero no es así. :( UnauthorizedAccessException en File.Delete (ruta); – Ase

+0

¿Se puede eliminar el archivo si no se carga primero el ensamblaje? –

8

Sé que este hilo es bastante muerto, pero actualmente estoy trabajando en esto y yo acabamos de la respuesta (a la 1:30 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(); 
} 

¡Y en realidad no arroja ninguna excepción! ¡Espero que alguien lea esto y que responda la pregunta!

+0

Esto es correcto. Esto debería funcionar. La razón por la que no funciona de otra manera es cuando se llama a 'app.Load()', el ensamblaje se carga en la aplicación de dominio de la aplicación, así como en el dominio de la aplicación en la que se está ejecutando el código. Después de descargar 'app', el ensamblaje aún se carga en el otro dominio de la aplicación. El uso de 'app.DoCallBack' hace que el código se ejecute en' app' y, por lo tanto, el ensamblaje solo se carga en 'app'. (fuentes: http://msdn.microsoft.com/en-us/library/36az8x58.aspx y http://msdn.microsoft.com/en-us/library/system.appdomain.docallback.aspx) –

4

ver estas páginas:

Establecer un nuevo AppDomain AppDomainSetup con LoaderOptimization.MultiDomainHost

por ejemplo,

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