强制从程序集中卸载DLL

时间:2012-01-26 10:41:47

标签: c# dll process appdomain

我试图从我的.NET进程中卸载一个行为不端的第三方DLL,因为它似乎导致了一个问题,这个问题总是通过重新启动我的应用程序来解决。 而不是重新启动应用程序,我想删除并重新加载DLL。

使用LoadLibrary加载DLL并使用FreeLibrary删除(使用从P / Invoke网站获取的DllImport)。 当我调用LoadLibrary()时,我看到DLL出现在Process Explorer的DLL列表中,当我调用FreeLibrary()时,我看到DLL从DLL列表中消失 - 正如预期的那样。

但是,一旦我调用了第三方库的Initialize()函数,即使我事先调用相应的FreeLibrary()方法,Deinit()也不再从列表中删除DLL 。 调用库中的另一个函数没有这个问题。但是,在使用之前我必须Initialise()库!

我尝试通过在自己的AppDomain中创建DLL来隔离DLL,然后在释放DLL后卸载此域。

我从Initialize()Deinit()LoadLibrary()FreeLibrary()或创建或卸载AppDomain,都没有收到来自AppDomainstring 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(); 的错误返回代码或例外情况。< / p>

我使用以下代码创建AppDomain并初始化:

m_Module.Free();
m_Module = null;
if (m_Domain != null)
{
    AppDomain.Unload(m_Domain);
    m_Domain = null;
}

取消初始化和卸载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; } // ... }

{{1}}

最后,我的ThirdPartyModule程序集类:

{{1}}

这看起来应该像我预期的那样吗?如果没有,有没有其他方法可以确保我的进程完全卸载此DLL?

修改:更多信息

  • DLL包含本机代码,可能是从C / C ++编译的
  • 不幸的是,我的进程仅限于使用.NET 2(因此没有WCF解决方案)。
  • 我使用的是WinXP Pro x64 SP2,但解决方案必须兼容XP,Win7 x32 / x64等。
  • DLL用于与USB令牌通信

1 个答案:

答案 0 :(得分:4)

我建议实现一个单独的进程(EXE),您的应用程序将启动该进程,然后加载DLL。

这允许您在需要时终止进程...

我看到了几个如何沟通的选项 - 例如:

  • 您可以使用COM(如果将其实现为进程外COM服务器)
  • 您可以使用共享内存(性能非常高,请参阅this进行演练,this进行.NET 2包装)

由于您写道该方法必须与多个Windows版本兼容,而某些版本与桌面防火墙兼容,因此我不会对IPC使用任何“网络”。