我试图从我的.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将使用令牌
是DLL本机DLL? – Yahia
您可以在另一个进程中运行该DLL,并通过WCF与它通信。当你不想卸载它时,你可以简单地杀死整个过程。 – CodingBarfield
@Yahia - 是的,我认为这是一个C/C++ DLL。 –