强制从程序集中卸载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令牌通信

强制从程序集中卸载DLL

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

这允许你在需要的时候杀死这个过程…

我看到了几个关于如何沟通的选项,例如:

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

由于你写的方法必须与几个Windows版本兼容,有些版本带有桌面防火墙,我不会在IPC中使用任何"网络"。