How can I retrieve a process\'s fully-qualified path from its PID using C++ on Windows?
Have you tried QueryFullProcessImageName
?
I didn't have very much luck with GetModuleFileNameEx and QueryFullProcessImageName is only available on Vista or higher. I was however able to get the path for a process by using GetProcessImageFilename. It returns the windows kernel path but you can use QueryDosDevice to compare the device path returned by GetProcessImageFilename
with its proper drive path.
This page shows how to normalize an windows kernel path returned by GetProcessImageFilename
(see NormalizeNTPath
function):
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/c48bcfb3-5326-479b-8c95-81dc742292ab/
Sometimes GetModuleFileNameEx
returns the 299 error code (I don't know why)
The only method that works for all versions of Windows, including XP is in Nathan Moinvaziri answer:
check the provided url:
Windows API to Get a Full Process Path
Call OpenProcess to get a handle to the process associated with your PID. Once you have a handle to the process, call GetModuleFileNameEx to get its fully-qualified path. Don't forget to call CloseHandle when you're finished using the process handle.
Here's a sample program that performs the required calls (replace 1234 with your PID):
#include <windows.h>
#include <psapi.h> // For access to GetModuleFileNameEx
#include <tchar.h>
#include <iostream>
using namespace std;
#ifdef _UNICODE
#define tcout wcout
#define tcerr wcerr
#else
#define tcout cout
#define tcerr cerr
#endif
int _tmain(int argc, TCHAR * argv[])
{
HANDLE processHandle = NULL;
TCHAR filename[MAX_PATH];
processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, 1234);
if (processHandle != NULL) {
if (GetModuleFileNameEx(processHandle, NULL, filename, MAX_PATH) == 0) {
tcerr << "Failed to get module filename." << endl;
} else {
tcout << "Module filename is: " << filename << endl;
}
CloseHandle(processHandle);
} else {
tcerr << "Failed to open process." << endl;
}
return 0;
}
Some notes to Emerick Rogul's solution:
Don't forget to add 'psapi.lib' to linker (additional dependencies).
I also changed PROCESS_ALL_ACCESS
to PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
because I got:
Failed to open process.
If it's compiled as a 32 bit application it will fail to get the name of 64 bit processes ("Failed to get module filename.")