一个在DLL内部的函数是否可以卸载DLL?我需要这样做以确保DLL未被使用,然后写入DLL文件。
据我理解,这是可以做到的,有时甚至是必须这样做的(例如在使用CreateRemoteThread和其他方法进行dll注入时)。所以,
最初的回答:
FreeLibraryAndExitThread(hModule, 0)
将正好做到这一点。
FreeLibrary(hModule)
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)DllMain,
&hModule
)
当dll完成其工作时,请使用此方法:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, &__ImageBase, 0, NULL);
// terminate if dll run in a separate thread ExitThread(0);
// or just return out the dll
而 __ImageBase 是你的 dll 的 PE 头结构:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
我认为这不会起作用。使用来自外部的句柄调用FreeLibrary(LoadLibrary将从DLL外部调用),因为代码运行在一个将不再有效的内存位置。
即使这是可能的,它看起来像是一个糟糕的设计。也许你想制作一些更新程序或类似的东西。请解释一下你期望的结果是什么。从自身内部卸载DLL不是正确的方法。
LoadLibrary
加载DLL时,它会将引用计数加1。它永远不会减少它。然后,你调用GetModuleHandleEx
,它再次将其增加1(顺便说一下,句柄与DllMain参数中的相同)。现在你调用FreeLibraryAndExitThread
,它将计数减1。你最终得到一个引用计数为1的结果,而DLL永远不会被卸载! - ScienceDiscovererLoadLibrary
或GetModuleHandleEx
中的任意一个,不需要同时使用两者。我在上面的帖子中所说的是另一件事情。我是指如果你从DllMain
参数中获取了句柄,则不应该使用此句柄进行卸载,因为从DllMain
获取句柄根本不会增加引用计数。 - Roland Pihlakas