通过进程句柄,获得可执行文件的路径,主要有以下几种方法:
第一种方法:也是最常用的方法,是通过GetModuleFileNameEx函数获得可执行文件的模块路径,这个函数从Windows NT 4.0开始到现在的Vista系统都能使用,向后兼容性比较好。
【函数原型】调用失败将返回0。注:进程的句柄须有PROCESS_QUERY_INFORMATION 和 PROCESS_VM_READ权限。
DWORD
WINAPI
GetModuleFileNameExW(
__in HANDLE hProcess,//标进程的句柄
__in_opt HMODULE hModule,//目标模块的句柄(当此参数为NULL时函数返回的是进程可执行文件的路径)
__out_ecount(nSize) LPWSTR lpFilename,//存放路径的字符串缓冲区
__in DWORD nSize//表示缓冲区的大小
);
GetModuleFileNameEx 的使用例子:
#include <Psapi.h>
#pragma comment (lib,"Psapi.lib")
//...
HANDLE h_Process=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,ProcessID);
wchar_t path[MAX_PATH+1];
if(!GetModuleFileNameEx(h_Process,NULL,path,MAX_PATH+1))
return false;
//...
注意:GetModuleFileNameEx函数在64位系统下,获取不到64位进程的可执行文件路径。
第二种方法:GetProcessImageFileName函数,这个函数在Windows XP及其以后的系统中都能使用,使用此函数返回的路径不是通常的系统盘符,如"C:\...",而是驱动层的表示方式"\Device\HarddiskVolume1\...",所以使用起来不是很方便。
【函数原型】函数失败将返回0。注:进程句柄需要有PROCESS_QUERY_INFORMATION的权限。
DWORD
WINAPI
GetProcessImageFileNameW (
__in HANDLE hProcess,//目标进程的句柄
__out_ecount(nSize) LPWSTR lpImageFileName,//存放路径的字符串缓冲区
__in DWORD nSize//表示缓冲区的大小
);
注意:调用 GetModuleFileNameEx 和 GetProcessImageFileName 需要包含Psapi.h头文件,并链接到Psapi.lib。
第三种方法:使用Windows Vista新增的函数QueryFullProcessImageName,由于是Vista新增的,所以兼容性不好。
【函数原型】函数失败将返回FALSE。
BOOL
WINAPI
QueryFullProcessImageNameW(
__in HANDLE hProcess,//目标进程的句柄
__in DWORD dwFlags,//一般设为0,表示返回的路径是Win32的路径格式,如"C:\..."
__out_ecount_part(*lpdwSize, *lpdwSize) LPWSTR lpExeName,//存放路径的字符串缓冲区
__inout PDWORD lpdwSize//表示缓冲区的大小
);
/// @brief 获取指定进程所对应的可执行(EXE)文件全路径
/// @param[in] hProcess : 进程句柄。
/// @param[out] szFilePath : 进程句柄hProcess所对应的可执行文件路径
/// @remark hProcess必须具有PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 权限
/// @return 获取成功返回true,其余false
bool GetProcessFilePath(IN HANDLE hProcess, OUT std::wstring& szFilePath)
{
szFilePath = _T("");
TCHAR tsFileDosPath[MAX_PATH + 1];
ZeroMemory(tsFileDosPath, sizeof(TCHAR)*(MAX_PATH + 1));
if (0 == GetProcessImageFileName(hProcess, tsFileDosPath, MAX_PATH + 1))
{
return false;
}
// 获取Logic Drive String长度
UINT uiLen = GetLogicalDriveStrings(0, NULL);
if (0 == uiLen)
{
return false;
}
PTSTR pLogicDriveString = new TCHAR[uiLen + 1];
ZeroMemory(pLogicDriveString, uiLen + 1);
uiLen = GetLogicalDriveStrings(uiLen, pLogicDriveString);
if (0 == uiLen)
{
delete[]pLogicDriveString;
return false;
}
TCHAR szDrive[3] = TEXT(" :");
PTSTR pDosDriveName = new TCHAR[MAX_PATH];
PTSTR pLogicIndex = pLogicDriveString;
do
{
szDrive[0] = *pLogicIndex;
uiLen = QueryDosDevice(szDrive, pDosDriveName, MAX_PATH);
if (0 == uiLen)
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
break;
}
delete[]pDosDriveName;
pDosDriveName = new TCHAR[uiLen + 1];
uiLen = QueryDosDevice(szDrive, pDosDriveName, uiLen + 1);
if (0 == uiLen)
{
break;
}
}
uiLen = _tcslen(pDosDriveName);
if (0 == _tcsnicmp(tsFileDosPath, pDosDriveName, uiLen))
{
wchar_t buf[1024];
swprintf_s(buf, 1024, L"%s%s", szDrive, tsFileDosPath + uiLen);
wchar_t *pstr = buf;
szFilePath = std::wstring(pstr);
break;
}
while (*pLogicIndex++);
} while (*pLogicIndex);
delete[]pLogicDriveString;
delete[]pDosDriveName;
return true;
}