Descargar una DLL cargada usando DllImport


¿Cómo puedo descargar una DLL que se ha cargado usando DllImport en C#?

Author: g t, 2010-03-15

5 answers

La forma más confiable de descargar una DLL no administrada de un proceso que se cargó mediante una declaración [DllImport] pinvoke es cargarla usted mismo, de nuevo, pinvoking LoadLibrary(). Eso le da un control confiable a la DLL y funciona correctamente incluso si el nombre del módulo de la DLL es ambiguo. No tiene ningún efecto en tiempo de ejecución, aparte del cargador de Windows que aumenta el recuento de referencias internas en la DLL de 1 a 2.

Entonces puedes pinvoke FreeLibrary () dos veces para disminuya el recuento de referencias a 0, pasándole el IntPtr que obtuvo de LoadLibrary (). Que descarga la DLL, así como cualquier DLL dependiente que se cargó.

Tenga cuidado de que obtendrá un fallo muy desagradable cuando intente pinvoke cualquierfunción exportada en el DLL de nuevo, cualquier tiempo después de hacer esto. El marshaller de pinvoke no sabe que el DLL ya no está y llamará a la función a la dirección que cree que sigue siendo válida. Que bombardea su programa con un AccessViolation excepción si tienes suerte. O ejecuta un bit de código completamente aleatorio si no tiene tanta suerte y el espacio de direcciones anteriormente ocupado por la DLL se reutilizó por otra DLL. Cualquier cosa puede pasar entonces, nada bueno.

 22
Author: Mitch Wheat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-11 13:55:12

Esto debería liberar un módulo previamente cargado cuando se llamó a la función P/Invoke.

[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);

public static void UnloadModule(string moduleName)
{
    foreach(ProcessModule mod in Process.GetCurrentProcess().Modules)
    {
        if(mod.ModuleName == moduleName)
        {
            FreeLibrary(mod.BaseAddress);
        }
    }
}
 8
Author: IllidanS4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-11 11:38:57

Basado en la recomendación de Peters, esto funciona para mí:

    [DllImport("kernel32", SetLastError = true)]
    private static extern bool FreeLibrary(IntPtr hModule);

    public static void UnloadImportedDll(string DllPath)
    {
        foreach (System.Diagnostics.ProcessModule mod in System.Diagnostics.Process.GetCurrentProcess().Modules)
        {
            if (mod.FileName == DllPath)
            {
                FreeLibrary(mod.BaseAddress);
            }
        }
    }
 3
Author: stefan.seeland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-02 09:14:14

Ya que me encontré con la información aquí mientras buscaba información, me imagino que contribuiré de nuevo con lo que terminé haciendo para solucionar un problema con el SDK Sixense en OSX EN UNITY. Verás allí una implementación de carga/descarga dinámica de un dylib en OSX:

Https://gist.github.com/amirebrahimi/d7b02c01bcd3ca7da144

 -1
Author: Amir Ebrahimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-19 18:20:20

Por si acaso si eres fan de la programación funcional, puedes usar LINQ para lograr lo que @IllidanS4 ha sugerido:

[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);

public static void UnloadModule(string moduleName)
{
   var loadedAssemblyModule =
            Process.GetCurrentProcess().Modules.OfType<ProcessModule>()
                .FirstOrDefault(x => x.ModuleName == moduleName);

   if (loadedAssemblyModule != null)
       FreeLibrary(loadedAssemblyModule.BaseAddress);
}
 -1
Author: RBT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 23:13:25