2010-08-04 102 views
2

DLL內部的函數是否可以卸載DLL?我需要這樣做,以便確保DLL未被使用,然後寫入DLL的文件。DLL卸載本身

回答

2

我不認爲它會起作用。使用外部句柄(LoadLibrary將從DLL之外的區域調用)調用FreeLibrary,因爲代碼在內存位置中運行,該內存位置不再有效。

即使這是可能的,它聞起來像一個糟糕的設計。也許你想做一些更新或相似。多解釋一下你期望的結果。從本身卸載DLL並不是要走的路。

+1

請參閱我有關FreeLibraryAndExitThread函數的回答 – 2013-11-29 07:08:15

+0

如果在DLL中有後臺線程,則調用FreeLibrary並不是最佳選擇。最好使用[FreeLibraryAndExitThread](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683153(v = vs.85).aspx)。這個功能是可以殺死2只鳥的岩石。 – 2015-07-06 18:32:57

0

如果你問你是否可以安全地從DLL本身的代碼中卸載/取消映射某個進程中加載​​的DLL,答案是否定的 - 沒有真正安全的方法來做到這一點。

想想這樣:卸載DLL是通過使用FreeLibrary()來減少引用計數來完成的。問題當然是,一旦DLL的引用計數達到零,模塊就不會被映射。這意味着稱爲FreeLibrary()的DLL中的代碼已經消失。

即使你可以這樣做,仍然需要確保沒有其他線程執行DLL中的任何導出函數。

4

使用此當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; 
+0

這個技巧可能會有所幫助,但理論上講,如果調用CreateThread的線程在CreateThread調用後過久,它仍然可能導致競爭狀態。請參閱有關FreeLibraryAndExitThread函數的答案。 – 2013-11-29 07:09:31

11

據我瞭解,它可以做,有時候是想做(例如,通過CreateRemoteThread和其他方法注入dll)。所以,

FreeLibraryAndExitThread(hModule, 0) 

將做到這一點。

在另一方面,呼籲

FreeLibrary(hModule) 

不會在這裏做的 - 從MSDN:「如果他們要分開調用FreeLibrary和了ExitThread,競爭條件將存在該庫可以了ExitThread之前卸載叫做。」作爲一個評論,ExitThread除了從線程函數返回之外還做了一些記錄。

這一切都假定您的DLL獲得的HMODULE本身從加載的DLL中調用調用LoadLibrary,或者說,從加載的DLL中調用以下功能:

GetModuleHandleEx 
(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
    (LPCTSTR)DllMain, 
    &hModule 
) 

這增加引用所以你知道,如果你以後使用該句柄釋放庫並且如果庫真的被卸載了,那麼你有最後一個參考。
如果改爲跳過遞增DLL的引用計數,並在DLL_PROCESS_ATTACH剛剛從參數的DllMain獲得HMODULE那麼你不應該因爲這加載的DLL中的代碼仍然使用它,這個模塊調用的FreeLibraryAndExitThread處理真的不是你的管理。