在运行时获取DLLpath

我想从代码中得到一个dll的目录(或文件)path。 (不是程序的.exe文件path)

我已经尝试了一些我发现的方法:
GetCurrentDir – 获取当前目录path。
GetModuleFileName – 获取可执行文件的path。

那么我怎样才能找出在哪个DLL的代码?
我正在寻找类似于C#的Assembly.GetExecutingAssembly

 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 

….

 WCHAR DllPath[MAX_PATH] = {0}; GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)); 

我将使用GetModuleHandleEx函数并获取您的DLL中的静态函数的句柄。 你可以在这里find更多的信息。

之后,您可以使用GetModuleFileName从刚刚获得的句柄中获取path。 更多的信息在这里 。

一个完整的例子:

 char path[MAX_PARAM]; HMODULE hm = NULL; if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &localFunc, &hm)) { int ret = GetLastError(); fprintf(stderr, "GetModuleHandle returned %d\n", ret); } GetModuleFileNameA(hm, path, sizeof(path)); // path variable should now contain the full filepath to localFunc 

GetModuleFileName()可以在DLL代码中正常工作。 只要确保不要将第一个参数设置为NULL ,因为这将获得调用进程的文件名。 您需要改为指定DLL的实际模块实例。 您可以将它作为DLL的DllEntryPoint()函数中的input参数,只需将其保存到某个variables中,以备将来使用时使用。

尝试GetModuleFileName函数。

这里是一个Unicode,顶级投票答案的修订版本:

 CStringW thisDllDirPath() { CStringW thisPath = L""; WCHAR path[MAX_PATH]; HMODULE hm; if( GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPWSTR) &thisDllDirPath, &hm ) ) { GetModuleFileNameW( hm, path, sizeof(path) ); PathRemoveFileSpecW( path ); thisPath = CStringW( path ); if( !thisPath.IsEmpty() && thisPath.GetAt( thisPath.GetLength()-1 ) != '\\' ) thisPath += L"\\"; } else if( _DEBUG ) std::wcout << L"GetModuleHandle Error: " << GetLastError() << std::endl; if( _DEBUG ) std::wcout << L"thisDllDirPath: [" << CStringW::PCXSTR( thisPath ) << L"]" << std::endl; return thisPath; } 

我想实现类似的东西,除了想要将类似的function合并成一个.dll文件 – 但是不能使用__ImageBase,因为它是特定于.dll函数所在的位置。 我甚至试图覆盖使用方法

 GetDllPath( HMODULE hDll = (HMODULE) __ImageBase) 

但是,这也不起作用。 (出于某种原因,之后返回应用程序path。)

然后我想通了 – 为什么我不使用VirtualQuery,并使用函数指针,并从那里获取HMODULE。 但是,如何获得调用者的函数指针呢?

现在它回到调用堆栈确定 – 我不会打扰你所有的肮脏的细节,只要按照提到的链接的链接。

这是完整的代码快照:

 // // Originated from: https://sourceforge.net/projects/diagnostic/ // // Similar to windows API function, captures N frames of current call stack. // Unlike windows API function, works with managed and native functions. // int CaptureStackBackTrace2( int FramesToSkip, //[in] frames to skip, 0 - capture everything. int nFrames, //[in] frames to capture. PVOID* BackTrace //[out] filled callstack with total size nFrames - FramesToSkip ) { #ifdef _WIN64 CONTEXT ContextRecord; RtlCaptureContext(&ContextRecord); UINT iFrame; for (iFrame = 0; iFrame < (UINT)nFrames; iFrame++) { DWORD64 ImageBase; PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry(ContextRecord.Rip, &ImageBase, NULL); if (pFunctionEntry == NULL) { if (iFrame != -1) iFrame--; // Eat last as it's not valid. break; } PVOID HandlerData; DWORD64 EstablisherFrame; RtlVirtualUnwind(0 /*UNW_FLAG_NHANDLER*/, ImageBase, ContextRecord.Rip, pFunctionEntry, &ContextRecord, &HandlerData, &EstablisherFrame, NULL); if(FramesToSkip > (int)iFrame) continue; BackTrace[iFrame - FramesToSkip] = (PVOID)ContextRecord.Rip; } #else // // This approach was taken from StackInfoManager.cpp / FillStackInfo // http://www.codeproject.com/Articles/11221/Easy-Detection-of-Memory-Leaks // - slightly simplified the function itself. // int regEBP; __asm mov regEBP, ebp; long *pFrame = (long*)regEBP; // pointer to current function frame void* pNextInstruction; int iFrame = 0; // // Using __try/_catch is faster than using ReadProcessMemory or VirtualProtect. // We return whatever frames we have collected so far after exception was encountered. // __try { for (; iFrame < nFrames; iFrame++) { pNextInstruction = (void*)(*(pFrame + 1)); if (!pNextInstruction) // Last frame break; if (FramesToSkip > iFrame) continue; BackTrace[iFrame - FramesToSkip] = pNextInstruction; pFrame = (long*)(*pFrame); } } __except (EXCEPTION_EXECUTE_HANDLER) { } #endif //_WIN64 iFrame -= FramesToSkip; if(iFrame < 0) iFrame = 0; return iFrame; } //CaptureStackBackTrace2 // // Gets .dll full path or only directory. // CStringW GetDllPath( bool bPathOnly /* = false */ ) { void* pfunc = &GetDllPath; wchar_t path[MAX_PATH] = { 0 }; MEMORY_BASIC_INFORMATION info; HMODULE hdll; CaptureStackBackTrace2(1, 2, &pfunc); // Get the base address of the module that holds the current function VirtualQuery(pfunc, &info, sizeof(MEMORY_BASIC_INFORMATION)); // MEMORY_BASIC_INFORMATION::AllocationBase corresponds to HMODULE hdll = (HMODULE)info.AllocationBase; // Get the dll filename if ( !GetModuleFileName( hdll, path, MAX_PATH ) ) return L""; if ( bPathOnly ) { wchar_t* p = wcsrchr( path, '\\' ); if ( p ) *p = 0; } return path; } //GetDllPath 
 HMODULE hmod = GetCurrentModule(); TCHAR szPath[MAX_PATH + 1] = 0; DWORD dwLen = GetModuleFileHName(hmod, szPath, MAX_PATH);