2012-01-26 93 views
11

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

使用LoadLibrary加载DLL并使用FreeLibrary(使用从P/Invoke网站获取的DllImport)加载DLL。 当我打电话给LoadLibrary()时,我看到DLL出现在Process Explorer中的DLL列表中,当我调用FreeLibrary()时,我发现该DLL从DLL列表中消失 - 正如所料。

但是,一旦我呼吁第三方库的Initialize()功能,FreeLibrary()不再从列表中删除该DLL,即使我打电话相应Deinit()方法事先。 在库中调用另一个函数没有这个问题。但是,我必须使用Initialise()库才能使用!

我试图通过在自己的AppDomain中创建它来隔离该DLL,然后在释放该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(); 

要deinitialise和卸载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++
  • 不幸的是我的过程局限于使用.NET 2只(所以没有WCF的解决方案)。
  • 我使用WinXP Pro x64 SP2,但解决方案必须是XP,Win7 x32/x64等兼容。
  • DLL将使用令牌
+0

是DLL本机DLL? – Yahia

+4

您可以在另一个进程中运行该DLL,并通过WCF与它通信。当你不想卸载它时,你可以简单地杀死整个过程。 – CodingBarfield

+0

@Yahia - 是的,我认为这是一个C/C++ DLL。 –

回答

4

一个USB我建议实行一个单独的进程(EXE),它在应用程序启动并依次加载DLL进行通信。

这使您可以在需要时终止进程......

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

  • 你可以使用COM(如果你实现它的过程外的一个COM服务器)
  • 你可以使用共享内存(非常高的性能,看到this的演练和this对于.NET 2包装)

既然你写的方法必须与几个Windows版本兼容和一些配有桌面防火墙我会避免来回m使用IPC的任何“网络”。