我试图从我的.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
,都没有收到来自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();
的错误返回代码或例外情况。< / 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?
修改:更多信息