Eliminar dll que estoy usando

Iniciado por El Benjo, 5 Agosto 2015, 09:31 AM

0 Miembros y 1 Visitante están viendo este tema.

El Benjo

Hola, buen día. Actualmente estoy trabajando en un proyecto donde importo un ensamblado y hago una instancia de una clase definida en ese ensamblado. La cuestión es que tengo un botón cuya acción es borrar el archivo de dicha dll, sin embargo el método File.Delete() me arroja una excepción de tipo UnauthorizedAccessException. He intentado eliminar la instancia que tengo de dicha clase dentro del ensamblado, pero al parecer esto no es suficiente. ¿Cómo puedo hacerlo, si es que puedo?
www.es.neftis-ai.com

Sí hay un mejor lenguaje de programación y es ese con el que puedes desarrollar tus objetivos.

Eleкtro

#1
Por mucho que liberes/finalices la instancia de la class, seguirá existiendo la instancia del archivo (la carga en memoria), por lo que el archivo seguirá estando "en uso".

Como nos indica la documentación en la MSDN, un ensamblado referenciado se carga al inicio de la app y su tiempo de vida es el mismo que el de la app, así que teoricamente no se puede liberar el ensamblado, a menos que liberes el AppDomain donde se cargó la dll (el entorno donde la app se está ejecutando), lo que viene siendo hasta finalizar la app...

How to: Load and Unload Assemblies (C# and Visual Basic) - MSDN




Se me ocurren dos soluciones viables (al menos).

La primera opción consiste en mover el archivo hacia una carpeta temporal para dejar que Windows lo elimine automaticamente más tarde en la siguiente limpieza del sistema.

Código (vbnet) [Seleccionar]
' ClassName = El nombre de la class del ensamblado referenciado.
Dim sourcePath As String = Assembly.GetAssembly(GetType(ClassName)).Location()
Dim targetPath As String = String.Format("{0}.tmp", Path.Combine(Path.GetTempPath, Path.GetFileName(sourcePath)))

File.Move(sourcePath, targetPath)


Nota(s):

  • Ten en cuenta que al mover el archivo los handles del archivo permanecerán, el ensamblado seguirá cargado en memoria obviamente, es una eliminación "a largo plazo".
  • En C# usarías la función typeof en lugar de GetType que no está disponible.




La segunda opción sería cargar el ensamblado dinamicamente mediante el uso de Reflection, usando el overload del método Load que toma como parámetro un stream o un array de bytes.

Código (vbnet) [Seleccionar]
Dim assPath As String = ".\MyAssembly.dll"
Dim ass As Assembly = Assembly.Load(File.ReadAllBytes(assPath))
File.Delete(assPath)

Nota(s):

  • si usases el método LoadFile para cargar un archivo local entonces no podrás eliminar el archivo.
  • Esta última opción requiere mucho más trabajo dependiendo de tus necesidades, de la cantidad de métodos miembros que necesitas localizar y usar mediante Reflection.

Saludos








El Benjo

Hola, Elektro, gracias por responder.

De hecho el proyecto carga un ensamblado en tiempo de ejecución y lo hacía con el método LoadFile() y no Load(). Todavía no pruebo el código porque en base a esta última modificación debo hacer varias modificaciones ya que se modifican algunas propiedades del objeto Assembly que devuelve. Pero en cuanto pruebe el código posteo si se ha solucionado.

De nuevo, muchas gracias, Elektro.
www.es.neftis-ai.com

Sí hay un mejor lenguaje de programación y es ese con el que puedes desarrollar tus objetivos.

El Benjo

Pues sí, la solución que me has dado con Assembly.Load en vez de Aseembly.LoadFile ha servido. Muchas gracias. :)
www.es.neftis-ai.com

Sí hay un mejor lenguaje de programación y es ese con el que puedes desarrollar tus objetivos.