Get runtime dll path

I want to get the dll directory (or file) from my code. (not the path to the .exe program file)

I tried several methods that I found:
GetCurrentDir - Gets the current directory path.
GetModuleFileName - Gets the executable path.

So, how can I find out which DLL the code is in?
I'm looking for something similar to C # Assembly.GetExecutingAssembly

+54
c ++ dll
Aug 03 2018-11-11T00:
source share
10 answers

You can use the GetModuleHandleEx function and get a pointer to a static function in your DLL. You will find more information here .

After that, you can use GetModuleFileName to get the path from the handle you just received. Learn more about this call here .

Full example:

 char path[MAX_PATH]; HMODULE hm = NULL; if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &functionInThisDll, &hm) == 0) { int ret = GetLastError(); fprintf(stderr, "GetModuleHandle failed, error = %d\n", ret); // Return or however you want to handle an error. } if (GetModuleFileName(hm, path, sizeof(path)) == 0) { int ret = GetLastError(); fprintf(stderr, "GetModuleFileName failed, error = %d\n", ret); // Return or however you want to handle an error. } // The path variable should now contain the full filepath for this DLL. 
+94
Aug 03 2018-11-11T00:
source share
 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 

....

 WCHAR DllPath[MAX_PATH] = {0}; GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)); 
+34
Aug 03 '11 at 9:25 a.m.
source share

GetModuleFileName() works fine inside DLLs. Just make sure NOT to set the first parameter to NULL , as this will get the file name of the calling process. Instead, you need to specify an instance of the actual DLL module. You get this as an input parameter in the DllEntryPoint() DLL function, just store it in a variable somewhere for later use when necessary.

+17
May 18 '12 at 4:54 a.m.
source share
+1
Aug 03 2018-11-11T00:
source share

Here's Unicode, a revised version of the top voted answer:

 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; } 
+1
Jul 02 '15 at 12:54
source share

For Delphi users:

 SysUtils.GetModuleName(hInstance); //Works; hInstance is a special global variable SysUtils.GetModuleName(0); //Fails; returns the name of the host exe process SysUtils.GetModuleName(GetModuleFilename(nil)); //Fails; returns the name of the host exe process 

If your Delphi does not have SysUtils.GetModuleName, it is declared as:

 function GetModuleName(Module: HMODULE): string; var modName: array[0..32767] of Char; //MAX_PATH is for a single filename; paths can be up to 32767 in NTFS - or longer. begin { Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process. } SetString(Result, modName, GetModuleFileName(Module, modName, Length(modName))); end; 
+1
Jun 01 '18 at 20:32
source share

I wanted to achieve something similar, except that I would like to make a similar function in one .dll - but then you cannot use __ImageBase, since it is specific to this .dll where the function is located. I even tried to override using the approach

 GetDllPath( HMODULE hDll = (HMODULE) __ImageBase) 

But that didn't work either. (For some reason, it returns the path to the program after that.)

Then I figured out why I am not using VirtualQuery, and I use a function pointer and get HMODULE from there. But then again - how to get the function pointer of the caller?

And now he returns to the definition of the call stack - I will not bother you with all the dirty details, just follow the links of the links mentioned.

Here is a complete snapshot of the code:

 // // 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 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 
0
Oct 23 '16 at 19:55
source share

Assuming you have implemented the following dll entry point: (usually dllmain.cpp)

 BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) 

You can simply do:

 switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { TCHAR dllFilePath[512 + 1] = { 0 }; GetModuleFileNameA(hModule, dllFilePath, 512) } break; case DLL_THREAD_ATTACH: break; ... 
Then

dllFilePath will contain the path where the current dll code was loaded. In this case, the hModule is passed by the process loading the dll.

0
Jun 19 '18 at 13:41
source share

IMHO, the Lebaus remy answer is the best, but, like everyone else, it is not enough to display the DLL directory. I quote the original question: "I want to get the path to the directory (or file) of the DLL from its code. (Not the path to the program's .exe file). 'I will develop two functions inside the DLL, the first will return a fully qualified name, the second will be fully qualified path. Assume that the full name of the DLL is "C: \ Bert \ Ernie.dll", then the functions return "C: \ Bert \ Ernie.dll" and "C: \ Bert" respectively. As Remi and Jean-Marc noted. DllMain , the DllMain DLL input function, usually found in dllmain.cpp, provides a DLL library descriptor, which is often needed, so it will be saved in g hMod global variable:

 HMODULE hMod; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } hMod = hModule; return TRUE; } 

Now, in the TestDll.cpp file, I define the GetFullyQualifiedNameOfDLL(wchar_t* PathFile) function GetFullyQualifiedNameOfDLL(wchar_t* PathFile) , which displays the full name, in our example "C: \ Bert \ Ernie.dll" and the GetFullyQualifiedPathToDLL(wchar_t * Path) function, which returns only the path here. "C : \ Bert '

 // TestDll.cpp : Defines the exported functions for the DLL application. #include "stdafx.h" extern HMODULE hMod; extern "C" __declspec(dllexport) DWORD _stdcall GetFullyQualifiedNameOfDLL(wchar_t * PathFile) { return ::GetModuleFileNameW(hMod, PathFile, MAX_PATH); } extern "C" __declspec(dllexport) DWORD _stdcall GetFullyQualifiedPathToDLL(wchar_t * Path) { wchar_t PathFile[MAX_PATH]; if (GetFullyQualifiedNameOfDLL(PathFile) == 0) { return 0; } wchar_t *pszFileName; DWORD FLen = ::GetFullPathNameW(PathFile, MAX_PATH, Path, &pszFileName); if (FLen == 0 || FLen >= MAX_PATH) { return 0; } *pszFileName = 0; return 1; } 

These functions can be used inside a DLL. A user of this DLL can call these functions as follows:

 void _tmain(int argc, TCHAR *argv[]) { wchar_t PathFile[MAX_PATH], Path[MAX_PATH]; GetFullyQualifiedNameOfDLL(PathFile); wprintf(L"Fully qualified name: %s\n", PathFile); //Split the fully qualified name to get the path and name std::wstring StdPath = PathFile; size_t found = StdPath.find_last_of(L"/\\"); wprintf(L"Path: %s, name: %s\n", StdPath.substr(0, found).c_str(), StdPath.substr(found + 1).c_str()); GetFullyQualifiedPathToDLL(Path); wprintf(L"Path: %s\n", Path); } 
0
Aug 31 '19 at 14:33
source share
 HMODULE hmod = GetCurrentModule(); TCHAR szPath[MAX_PATH + 1] = 0; DWORD dwLen = GetModuleFileHName(hmod, szPath, MAX_PATH); 
-four
Aug 03 2018-11-11T00:
source share



All Articles