DLL内的函数是否可以卸载DLL?我需要这样做,所以我可以确保DLL没有被使用,然后写入DLL的文件。
答案 0 :(得分:13)
据我所知,它可以完成,并且有时候很有意义(例如在CreateRemoteThread和其他方法注入dll的情况下)。所以,
FreeLibraryAndExitThread(hModule, 0)
就是这样做的。
另一方面,呼叫
FreeLibrary(hModule)
不会在这里 - 来自MSDN:“如果他们分别调用FreeLibrary和ExitThread,就会存在竞争条件。可以在调用ExitThread之前卸载库。”作为评论,除了从线程函数返回外,ExitThread还会进行一些簿记。
所有这些都假设你的Dll通过从加载的Dll中调用 LoadLibrary 来获得hModule本身,或者更确切地说,通过从加载的Dll内部调用以下函数来获取hModule:
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)DllMain,
&hModule
)
这会增加Dll的引用计数,因此您知道如果您稍后使用该句柄释放库,并且如果该库实际上已卸载,那么您最后一次引用它。
如果您改为在 DLL_PROCESS_ATTACH 期间跳过递增Dll的引用计数并仅从 DllMain 的参数获取hModule,那么您不应该调用 FreeLibraryAndExitThread ,因为加载Dll的代码仍在使用它,这个模块句柄实际上不是你需要管理的。
答案 1 :(得分:5)
当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;
答案 2 :(得分:2)
我认为它不会起作用。使用外部句柄调用FreeLibrary(LoadLibrary将从DLL外部区域调用),因为代码在内存位置运行,不再有效。
即使这是可能的,它也闻起来像一个糟糕的设计。也许你想制作一些更新程序或类似的。再解释一下你期望的结果。从内部卸载DLL是不可取的。
答案 3 :(得分:0)
如果您询问是否可以安全地从DLL本身的代码中卸载/取消映射进程中加载的DLL,答案是否定的 - 实际上没有一种安全的方法可以执行此操作。
这样考虑:卸载DLL是通过使用FreeLibrary()减少它的引用计数来完成的。问题当然是一旦DLL的引用计数达到零,模块就会被取消映射。这意味着DLL中调用FreeLibrary()的代码消失了。
即使你可以这样做,你仍然需要确保没有其他线程从DLL执行任何导出的函数。