强制从程序集中卸载DLL
本文关键字:集中 卸载 DLL 程序集 程序 | 更新日期: 2023-09-27 18:21:33
我正试图从.NET进程中卸载一个行为不端的第三方DLL,因为它似乎导致了一个问题,这个问题总是可以通过重新启动应用程序来解决。我不想重新启动应用程序,而是想删除并重新加载DLL。
使用LoadLibrary
加载DLL,使用FreeLibrary
删除DLL(使用从p/Invoke网站获取的DllImport
)。当我调用LoadLibrary()
时,我会看到DLL出现在Process Explorer的DLL列表中,当我调用FreeLibrary()
时,我看到DLL从DLL列表中消失——正如预期的那样。
但是,一旦我调用了第三方库的Initialize()
函数,即使我事先调用了相应的Deinit()
方法,FreeLibrary()
也不再从列表中删除DLL。调用库中的另一个函数没有这个问题。但是,在使用之前,我必须先Initialise()
库!
我尝试过隔离DLL,方法是在它自己的AppDomain
中创建它,然后在释放DLL后卸载此域。
我没有从Initialize()
或Deinit()
、LoadLibrary()
或FreeLibrary()
或创建或卸载AppDomain
得到错误返回代码或异常。
我使用以下代码创建AppDomain
并初始化:
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();
要取消初始化并卸载AppDomain
:
m_Module.Free();
m_Module = null;
if (m_Domain != null)
{
AppDomain.Unload(m_Domain);
m_Domain = null;
}
最后,我的ThirdPartyModule组装类:
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;
}
// ...
}
这看起来应该像我预期的那样吗?如果没有,有没有其他方法可以确保我的进程完全卸载这个DLL?
编辑:更多信息
- DLL包含本机代码,可能是从C/C编译的++
- 不幸的是,我的进程仅限于使用.NET2(因此没有WCF解决方案)
- 我使用的是WinXP Pro x64 SP2,但解决方案必须与XP、Win7 x32/x64等兼容
- DLL用于与USB令牌通信
我建议实现一个单独的进程(EXE),应用程序启动该进程,然后加载DLL。
这允许你在需要的时候杀死这个过程…
我看到了几个关于如何沟通的选项,例如:
- 可以使用COM(如果将其实现为进程外的COM服务器)
- 您可以使用共享内存(非常高的性能,请参阅此演练和此.NET 2包装器)
由于你写的方法必须与几个Windows版本兼容,有些版本带有桌面防火墙,我不会在IPC中使用任何"网络"。