The obvious question would be why you don't just use QueryFullProcessImageName
, if that's what you want? Do you need compatibility with older versions of Windows?
The closest equivalent to QueryFullProcessImageName
that's available on XP is probably GetModuleFileNameEx
. I'd probably detect whether QueryFullProcessImageName
is available and use it if possible, otherwise fall back to GetModuleFileNameEx
.
Edit: While GetModuleFileNameEx
isn't 100% dependable at retrieving the name of the executable for every possible process, it does work at least a fairly substantial part of the time. Here's a quick bit of test code I put together:
#include <windows.h>
#include <psapi.h>
#include <iostream>
#include <string>
#include <map>
std::string getfilename(DWORD pid) {
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
static int winver;
char path[256]= {0};
DWORD size = sizeof(path);
if (winver==0)
winver = GetVersion() & 0xf;
#if WINVER >= 0x600
if (winver >= 6)
QueryFullProcessImageName(process, 0, path, &size);
else
#endif
if (!GetModuleFileNameEx(process, NULL, path, sizeof(path)))
strcpy(path, "Unknown");
return std::string(path);
}
typedef std::map<DWORD, std::string> win_map;
namespace std {
ostream &operator<<(ostream &os, win_map::value_type const &v) {
return os << v.first << ": " << v.second;
}
}
BOOL CALLBACK show_info(HWND window, LPARAM lParam) {
win_map &exes = *(win_map *)lParam;
DWORD pid;
GetWindowThreadProcessId(window, &pid);
exes[pid] = getfilename(pid);
return true;
}
int main() {
win_map exes;
EnumWindows(show_info, (LPARAM)&exes);
std::copy(exes.begin(), exes.end(), std::ostream_iterator<win_map::value_type>(std::cout, "\n"));
return 0;
}
The results of a quick test are somewhat interesting. Compiled as 32-bit code, the version using QueryFullProcessImageName
found 33 processes with top-level windows, and found names for 31 of those executables. The version using GetModuleFileNameEx
, also found 33 processes, but only found names for 21 of the executable. If, however, I compile it as 64-bit code, either version finds filenames for 31 out of 33 executables (and the same two fail). Given the frequency with which you see XP/x64, that's probably of little consequence, but I found it interesting nonetheless.
In any case, even the least capable version (32-bit/GMFNE) found names for ~2/3rds of the files. While that's certainly not what you'd hope for, it's certainly better than nothing.