Estoy intentando descargar una DLL de terceros que funciona mal de mi proceso .NET, ya que parece estar causando un problema que siempre se resuelve al reiniciar mi aplicación. En lugar de reiniciar la aplicación, me gustaría eliminar y volver a cargar la DLL.Descargue forzosamente DLL del ensamblado
La DLL se carga utilizando LoadLibrary
y se elimina utilizando FreeLibrary
(utilizando DllImport
s tomada del sitio web de P/Invoke). Cuando llamo al LoadLibrary()
veo que la DLL aparece en la lista de DLL en Process Explorer, y cuando llamo al FreeLibrary()
veo que la DLL desaparece de la lista de DLL, como se esperaba.
Sin embargo, una vez que he llamado la función Initialize()
de la biblioteca de terceros, FreeLibrary()
ya no elimina el archivo DLL de la lista, incluso si yo llamo un Deinit()
método correspondiente de antemano. Llamar a otra función en la biblioteca no tiene este problema. Sin embargo, debo Initialise()
la biblioteca antes de usar!
He intentado aislar la DLL creándola en su propia AppDomain
, y luego descargo este dominio después de liberar la DLL.
No me sale códigos de retorno de error o excepciones de Initialize()
o Deinit()
, desde el LoadLibrary()
o FreeLibrary()
o de crear o descargar la AppDomain
.
que utiliza el código siguiente para crear el AppDomain
e inicializar:
string pathToDll = Assembly.GetExecutingAssembly().CodeBase;
m_Domain = AppDomain.CreateDomain("MyAppDomain", null, new AppDomainSetup { PrivateBinPath = pathToDll });
m_Module = (ThirdPartyModule)m_Domain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ThirdPartyModule).FullName);
m_Module.Init();
Para deinitialise y descargar el AppDomain
:
m_Module.Free();
m_Module = null;
if (m_Domain != null)
{
AppDomain.Unload(m_Domain);
m_Domain = null;
}
Por último, mi ThirdPartyModule clase de montaje:
internal class ThirdPartyModule : MarshalByRefObject
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool FreeLibrary(IntPtr hModule);
public IntPtr Module { get; set; }
public ThirdPartyModule()
{
Module = LoadLibrary("Misbehaving.dll");
}
public void Free()
{
FreeLibrary(Module);
Module = IntPtr.Zero;
}
// ...
}
Parece que debería comportarse como ¿Esperaba? Si no, ¿hay alguna otra forma en que pueda garantizar que este archivo DLL esté completamente descargado?
Edición: Más información
- El DLL contiene el código nativo, probablemente compilado de C/C++
- Desafortunadamente mi proceso está limitado al uso de .NET 2 solamente (por lo que no hay solución WCF).
- Estoy usando WinXP Pro x64 SP2 pero la solución debe ser compatible con XP, Win7 x32/x64, etc.
- La DLL se utiliza para comunicarse con un token USB
es la DLL una DLL nativa? – Yahia
Podría ejecutar el archivo DLL en otro proceso y comunicarse con él a través de WCF. Puedes simplemente matar todo el proceso cuando quieras descargarlo. – CodingBarfield
@Yahia: sí, creo que es una DLL C/C++. –