2011-02-03 16 views
24

Tengo una aplicación que carga un DLL para ejecutar una parte específica de procesamientocaliente Unload/Reload de un DLL utilizada por una aplicación

Example : "Application.dll" loading "Process.dll" 

Process.dll se carga dinámicamente en tiempo de ejecución, utilizando la reflexión, y no se hace referencia en la aplicación.

Una vez finalizado el procesamiento, la DLL debe recompilarse en el servidor y volver a cargarse más tarde.
Para poder hacerlo, necesito liberarlo, de lo contrario me sale el siguiente mensaje: "No se puede copiar el archivo" Process.dll "a" Process.dll ". El proceso no puede acceder al archivo 'Process.dll' porque está siendo utilizado por otro proceso ".

Así que la pregunta es: Cómo liberar/liberar/descargar programáticamente el Process.dll de mi aplicación antes de volver a cargarlo. Por supuesto, todo el punto es hacer esto SIN detener la aplicación.

EDIT 1:

Una solución propuesta es la siguiente:

AppDomain newDomain4Process = AppDomain.CreateDomain("newDomain4Process"); 
Assembly processLibrary = newDomain4Process.Load("Process.dll"); 
AppDomain.Unload(newDomain4Process); 

El problema sigo teniendo es que, a pesar de que estoy dando la ruta completa correcta, aparece un FileNotFound Exception. La respuesta a this post tampoco tuvo el efecto esperado.

EDIT 2:

This post salvaron mi vida, aquí está el código:

class ProxyDomain : MarshalByRefObject 
    { 
     public Assembly GetAssembly(string AssemblyPath) 
     { 
      try 
      { 
       return Assembly.LoadFrom(AssemblyPath); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 
    } 

    ProxyDomain pd = new ProxyDomain(); 
    Assembly a = pd.GetAssembly(FullDLLPath); 

Datos 3:
no he tenido acceso al dominio de aplicación y descargarla con la solución anterior sin embargo. Cuando utilicé el método clásico de creación de dominios de aplicaciones, sentí la advertencia de Alexei: AppDomain.Unload "parecía" funcionar, pero el ensamblaje aún estaba cargado (Vista de módulo). Así que todavía tengo mi problema de alguna manera, ya que realmente no puedo descargar el archivo DLL de manera eficiente.

+0

En cuanto a su Editar 3. Esto suena y ahora recuerdo que cuando lo probé me rendí debido a problemas similares y en su lugar fui a crear un archivo ejecutable contenedor muy simple que cargara el archivo DLL y mi ejecutable original se comunicó con la DLL a través de una interfaz COM. Luego, simplemente cerré el archivo ejecutable del contenedor cada vez que necesitaba cargar la nueva versión de la DLL, así que no tenía que preocuparme por los AppDomains. Esto funcionó bien para mí, ya que el rendimiento no era tan importante, por lo que tener el dll fuera de proceso no me afectó :) –

+0

Dude LOL. Estoy a punto de darme por vencido (al menos por el momento), ya que han pasado dos días y tengo la impresión de haber ingresado al Abismo. Mi vida ha sido una maldición de miseria ya que he estado tratando de meterme con todo lo que tenía, había toneladas de errores/problemas que parecían muy difíciles de resolver en un tiempo razonable y sin profundizar realmente en los conceptos para realmente entender lo que 'Estoy haciendo. Por el momento, tomaré un descanso por un tiempo y volveré a la buena codificación normal ya que tengo un proyecto para entregar :-) –

+0

Tenga cuidado con las compensaciones, la clasificación (serialización) ocurrirá entre los AppDomains. http://stackoverflow.com/questions/5600761/what-is-marshalling-what-is-happening-when-something-is-marshalled – gerleim

Respuesta

15

Ha pasado bastante tiempo desde que miré esto, pero estoy bastante seguro de que necesitaría crear una nueva AppDomain y luego cargar la DLL allí.

La razón es que no puede descargar un Assembly por sí mismo, pero puede descargar un AppDomain que contiene un Assembly.

Aquí hay un artículo CodeProject que describe cómo hacer esto: To Unload a Running Dll

+0

Correcto, no se puede "descargar" una DLL desde un dominio de aplicación –

+0

Así es, no hay forma de descargar un ensamblado desde un AppDomain una vez que está allí. – TToni

+0

Bien entonces. ¿Mi edición es correcta? Técnicamente hablando, ¿es eso suficiente para hacer el truco? Y, por cierto, ¿qué sucede detrás de las escenas? Los AppDomains son independientes, pero aún así, ¿pueden "comunicarse" ensamblajes entre ellos? –

6

Una vez que el montaje se ha cargado en un AppDomain, no se puede descargar. Debe deshacerse del AppDomain. Si necesita cargar y descargar ensamblajes dentro de una aplicación, necesitará generar un nuevo AppDomain y cargar el ensamblaje, luego destruya el AppDomain una vez que haya terminado con el ensamblaje.

6

Si bien parece que resolver el problema de acuerdo a su edición aquí están los comentarios de pareja:

cuidado con los objetos de su Process.dll "fugas" en dominio de aplicación principal. Es decir. algo así como lanzar una excepción personalizada definida en Process.dll y atrapada en AppDomain principal obligará a Process.dll a cargarse en AppDomain principal. Consulte la lista de ensamblados cargados en el AppDomain principal después de realizar las operaciones que le interesan.

La descarga de AppDomain puede fallar y puede llevar mucho tiempo.

+0

Heeeeeelp! ¡Caigo en el problema de las fugas! Amigo, son malas noticias. La vista Módulo muestra que el maldito ensamblaje aún está cargado. ¿De cualquier forma que pueda forzarlo? –

+3

No puede forzarlo: tan pronto se cargue en AppDomain particular, permanecerá allí. Debe evitar que los tipos de ese conjunto crucen el límite de AppDomain. Asegúrese de no devolver ningún objeto que esté definido en ese Ensamblaje. Es decir.Si devuelve un objeto que implementa la interfaz desde el ensamblaje principal, es posible que deba escribir una clase de proxy en el ensamblaje principal y devolverlo en su lugar. Espere pasar mucho tiempo obteniendo toda la historia con la carga de ensamblajes en el nuevo AppDomain correcto. –

Cuestiones relacionadas