I used to present a bug-fixed version of an MSDN sample here, but that code has been rendered useless by security changes in Vista. Fortunately, MS realised the size of the hole in their API and quietly filled it some time ago, to my annoyance:
UINT GetWindowModuleFileName (HWND hwnd, LPTSTR lpszFileName, UINT cchFileNameMax);If you're targetting an older version of Windows and can't guarantee the availability of this new API, try this code:
BOOL MyGetWindowExeFilename (HWND hWnd, char * pszFilename, int iSizeofBuff) { HANDLE hProc; HMODULE ahMod [10]; DWORD dwNeeded; DWORD dwPid; BOOL bResult = FALSE; // Get PID corresponding to this window handle. GetWindowThreadProcessId (hWnd, &dwPid); hProc = OpenProcess (PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, dwPid); if (hProc) { if (EnumProcessModules (hProc, ahMod, sizeof(ahMod), &dwNeeded)) { // we're only interested in the first module. if (GetModuleBaseName (hProc, ahMod[0], pszFilename, iSizeofBuff)) { bResult = TRUE; } } CloseHandle (hProc); } return bResult; }
Be aware that EnumProcessModules call can fail and then you'll need to compare the contents of dwNeeded with your array, expand and recall it. In practice I've never had to increase my code beyond 10 slots. YMMV, as always.
Download