DLL卸载自己

时间:2010-08-04 21:49:24

标签: dll self-reference

DLL内的函数是否可以卸载DLL?我需要这样做,所以我可以确保DLL没有被使用,然后写入DLL的文件。

4 个答案:

答案 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执行任何导出的函数。