如何查找加载程序DLL的路径?

时间:2016-03-02 07:06:57

标签: c++ winapi dll

我想读取我的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的名称。

当我阅读GetModuleFileName的MSDN帮助时,我在下面看到了关于函数的第一个参数的描述。

  

正在请求路径的已加载模块的句柄。如果这   参数为NULLGetModuleFileName检索路径   当前进程的可执行文件。

我不想获得可执行文件的路径,我只是想确定哪个DLL加载我当前的DLL。有没有办法找到加载器路径DLL?

2 个答案:

答案 0 :(得分: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"));
}

答案 1 :(得分:0)

您可以使用dllpath函数定义自己的路径,并将其作为参数传递给链接的路径。