Mit*_*eat 23
从[DllImport] pinvoke声明加载的进程中卸载非托管DLL的最可靠方法是通过pinvoking LoadLibrary()再次自己加载它.这为DLL提供了可靠的DLL处理,即使DLL的模块名称不明确,也能正常工作.它在运行时没有任何影响,除了Windows加载器将DLL的内部引用计数从1增加到2.
然后,您可以将FreeLibrary()两次旋转以将引用计数减少为0,并将其从LoadLibrary()传递给IntPtr.卸载DLL,以及任何加载的依赖DLL.
要注意的是,当你尝试的PInvoke你会得到非常讨厌失败的任何再次对DLL导出功能,任何这样做之后的时间.pinvoke marshaller不知道DLL不再存在,并且会在它认为仍然有效的地址处调用该函数.如果幸运的话,哪些程序会使用AccessViolation异常对您的程序进行轰炸.或者运行一个完全随机的代码,如果你不是那么幸运,以前DLL占用的地址空间被另一个DLL重用.任何事情都可能发生,没有一件好事.
Ill*_*ack 10
这应该释放先前在您调用P/Invoke函数时加载的模块.
[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadModule(string moduleName)
{
foreach(ProcessModule mod in Process.GetCurrentProcess().Modules)
{
if(mod.ModuleName == moduleName)
{
FreeLibrary(mod.BaseAddress);
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据彼得斯的推荐,这对我有用:
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadImportedDll(string DllPath)
{
foreach (System.Diagnostics.ProcessModule mod in System.Diagnostics.Process.GetCurrentProcess().Modules)
{
if (mod.FileName == DllPath)
{
FreeLibrary(mod.BaseAddress);
}
}
}
Run Code Online (Sandbox Code Playgroud)