2016-03-02 53 views
-1

我想讀取我的DLL的加載器DLL的二進制文件。但是有一個exe和2個DLL,我使用第一個(X DLL)作爲第二個loadind(Y DLL)。當我通過EXE載入X DLL的Y DLL時,GetModuleFileNameA(NULL, szEXEPath, 2048);函數給我一個EXE路徑。我想獲得X DLL路徑。我可以使用GetModuleFileNameA("X DLL Name", szEXEPath, 2048);但我不知道X DLL的名稱。如何找到加載器DLL的路徑?

當我讀取GetModuleFileName的MSDN幫助時,我看到在下面關於函數的第一個參數的描述。

正在請求路徑的加載模塊的句柄。如果此 參數爲NULL,則GetModuleFileName將檢索當前進程的可執行文件 的路徑。

我不想得到可執行文件的路徑,我只是想確定哪個DLL加載我當前的DLL。有沒有辦法找到加載程序路徑DLL?

+1

我不認爲有任何簡單的方法來做到這一點。一條痕跡可能? –

+1

我明白這意味着你想要「父」DLL的名稱,加載你的DLL的名稱(見下文)。有了一些幫助,這並不難。 – Niall

+0

安排X調用Y中的函數並提供信息 –

回答

0

您可以使用dllpath函數來定義自己的路徑並將其作爲參數傳遞給鏈接的路徑。

+0

如果我理解你的答案,你說「發送X DLL的名字或者像參數一樣的路徑」。其實我不想從外面指出X DLL的路徑或名稱。因爲我不會開發它,這對我的控制很重要。如果開發者始終發送相同的路徑或名稱,我無法檢查真正的加載器DLL。 – ceyun

+1

@ceyun:如果使用你的DLL的人不遵守規則,那麼DLL將無法正常工作,但這是他們的錯,而不是你的。根據Niall的回答,而不是一個字符串,要求提供一個模塊句柄(根據Niall的答案)可能是明智的,因爲這對於開發人員而言是較少的工作,但是您必須*從調用者那裏獲取信息 - 沒有其他方法可以做到這一點,因爲Windows不會跟蹤您要求的信息。 –

+0

但是,如果我在visualstudio中查看Y DLL的模塊,則會顯示其中的X DLL。我想我們可以從窗口保存的位置獲取這些信息。 – ceyun

1

要獲得「父」dll的名稱,您可以創建一個函數作爲需要調用的API的一部分,該函數通過父DLL的HMODULE句柄。

get_current_module_handle()函數創建爲inline並將其封裝到某種宏中可以簡化客戶端代碼的過程。

//... control header 
inline HMODULE get_current_module_handle() {/*...*/} 
#define PARENT_MODULE get_current_module_handle() 
void SetControlParent(HMODULE parent); 
//... client code to initialise the "parent" 
SetControlParent(PARENT_MODULE); 

要獲得DLL名稱(孩子),你可以使用的GetModuleFileNameExGetModuleHandleEx功能的組合。技巧是在GetModuleHandleEx函數中允許通過指向函數的指針(即dll中的函數)獲取模塊句柄;特別是使用標記GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS

接下來是一些代碼應該做的訣竅片段;

HMODULE get_current_module_handle() 
{ 
    HMODULE moduleHandle = NULL; 
    if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 
     (LPCTSTR)get_current_module_handle, &moduleHandle)) 
     throw std::runtime_error("unable to get the module handle"); 
    return moduleHandle; 
} 

std::basic_string<TCHAR> get_module_name(HMODULE moduleHandle) 
{ 
    std::vector<TCHAR> filename(2048, _T('?')); // allocate some space 
    DWORD filenameLength = ::GetModuleFileNameEx(::GetCurrentProcess(), moduleHandle, &filename.front(), filename.size()); 
    if (filenameLength && filenameLength < filename.size()) { 
     return std::basic_string<TCHAR>(&filename.front(), filenameLength); 
    } 
    return std::basic_string<TCHAR>(_T("unknown")); 
} 

//... 

std::basic_string<TCHAR> dllname = get_module_name(get_current_module_handle()); // current dll 
std::basic_string<TCHAR> parentdllname = get_module_name(parentHModule); // for "parent" dll 

的簡化版本被上述再現(基於OP 2048長度)。還提供了一個用於說明長文件名的遞歸實現(檢查編輯)。

dllname將是該模塊的完全限定路徑,因此獲取基本文件名,功能如_splitpath。或者,您可以直接在上面的代碼中使用GetModuleBaseName

std::basic_string<TCHAR> get_module_name(HMODULE moduleHandle) 
{ 
    std::vector<TCHAR> filename(MAX_PATH, _T('?')); // MAX_PATH is 260 
    DWORD filenameLength = ::GetModuleBaseName(::GetCurrentProcess(), moduleHandle, &filename.front(), filename.size()); 
    if (filenameLength && filenameLength < filename.size()) { 
     return std::basic_string<TCHAR>(&filename.front(), filenameLength); 
    } 
    return std::basic_string<TCHAR>(_T("unknown")); 
}