关闭

根据进程句柄 获得可执行文件路径 的几种方法

标签: GetModuleFileNameEx
2344人阅读 评论(0) 收藏 举报
分类:

通过进程句柄,获得可执行文件的路径,主要有以下几种方法:

第一种方法:也是最常用的方法,是通过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//表示缓冲区的大小
		);
dwFlags,如将其设为PROCESS_NAME_NATIVE将返回"\Device\HarddiskVolume1\..."这样的格式路径。调用此函数的句柄须有PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 的权限,并且只能在Vista或更高版本的系统中使用。

第四种方法:其实也是最靠谱的方法!使用GetProcessImageFileName ,不过该函数返回的格式是DOS格式,需要再通过与 LogicalDriveStrings 比对拼接出进程可执行文件的完整路径。方法如下:
/// @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;
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:231947次
    • 积分:4281
    • 等级:
    • 排名:第8000名
    • 原创:197篇
    • 转载:62篇
    • 译文:0篇
    • 评论:42条
    最新评论