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

转载自: http://blog.csdn.net/hellokandy/article/details/52160077

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

第一种方法:也是最常用的方法,是通过GetModuleFileNameEx函数获得可执行文件的模块路径,这个函数从Windows NT 4.0开始到现在的Vista系统都能使用,向后兼容性比较好。

【函数原型】调用失败将返回0。注:进程的句柄须有PROCESS_QUERY_INFORMATION 和 PROCESS_VM_READ权限。

[cpp]  view plain  copy
 print ?
  1. DWORD  
  2.         WINAPI  
  3.         GetModuleFileNameExW(  
  4.         __in HANDLE hProcess,//标进程的句柄  
  5.         __in_opt HMODULE hModule,//目标模块的句柄(当此参数为NULL时函数返回的是进程可执行文件的路径)  
  6.         __out_ecount(nSize) LPWSTR lpFilename,//存放路径的字符串缓冲区  
  7.         __in DWORD nSize//表示缓冲区的大小  
  8.         );  

GetModuleFileNameEx 的使用例子

[cpp]  view plain  copy
 print ?
  1. #include <Psapi.h>  
  2. #pragma comment (lib,"Psapi.lib")  
  3. //...  
  4. HANDLE h_Process=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,ProcessID);  
  5. wchar_t path[MAX_PATH+1];  
  6. if(!GetModuleFileNameEx(h_Process,NULL,path,MAX_PATH+1))  
  7.     return false;  
  8. //...  

注意:GetModuleFileNameEx函数在64位系统下,获取不到64位进程的可执行文件路径


第二种方法:GetProcessImageFileName函数,这个函数在Windows XP及其以后的系统中都能使用,使用此函数返回的路径不是通常的系统盘符,如"C:\...",而是驱动层的表示方式"\Device\HarddiskVolume1\...",所以使用起来不是很方便。

【函数原型】函数失败将返回0。注:进程句柄需要有PROCESS_QUERY_INFORMATION的权限。

[cpp]  view plain  copy
 print ?
  1. DWORD  
  2.         WINAPI  
  3.         GetProcessImageFileNameW (  
  4.         __in HANDLE hProcess,//目标进程的句柄  
  5.         __out_ecount(nSize) LPWSTR lpImageFileName,//存放路径的字符串缓冲区  
  6.         __in DWORD nSize//表示缓冲区的大小  
  7.         );  

注意:调用 GetModuleFileNameEx 和 GetProcessImageFileName 需要包含Psapi.h头文件,并链接到Psapi.lib。 


第三种方法:使用Windows Vista新增的函数QueryFullProcessImageName,由于是Vista新增的,所以兼容性不好。

【函数原型】函数失败将返回FALSE。

[cpp]  view plain  copy
 print ?
  1. BOOL  
  2.         WINAPI  
  3.         QueryFullProcessImageNameW(  
  4.         __in HANDLE hProcess,//目标进程的句柄  
  5.         __in DWORD dwFlags,//一般设为0,表示返回的路径是Win32的路径格式,如"C:\..."  
  6.         __out_ecount_part(*lpdwSize, *lpdwSize) LPWSTR lpExeName,//存放路径的字符串缓冲区  
  7.         __inout PDWORD lpdwSize//表示缓冲区的大小  
  8.         );  
dwFlags,如将其设为PROCESS_NAME_NATIVE将返回"\Device\HarddiskVolume1\..."这样的格式路径。调用此函数的句柄须有PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 的权限,并且只能在Vista或更高版本的系统中使用。

第四种方法:其实也是最靠谱的方法!使用GetProcessImageFileName ,不过该函数返回的格式是DOS格式,需要再通过与 LogicalDriveStrings 比对拼接出进程可执行文件的完整路径。方法如下:
[cpp]  view plain  copy
 print ?
  1. /// @brief      获取指定进程所对应的可执行(EXE)文件全路径  
  2. /// @param[in]  hProcess : 进程句柄。  
  3. /// @param[out] szFilePath : 进程句柄hProcess所对应的可执行文件路径  
  4. /// @remark     hProcess必须具有PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 权限  
  5. /// @return     获取成功返回true,其余false  
  6. bool GetProcessFilePath(IN HANDLE hProcess, OUT std::wstring& szFilePath)  
  7. {  
  8.     szFilePath = _T("");  
  9.     TCHAR tsFileDosPath[MAX_PATH + 1];  
  10.     ZeroMemory(tsFileDosPath, sizeof(TCHAR)*(MAX_PATH + 1));  
  11.     if (0 == GetProcessImageFileName(hProcess, tsFileDosPath, MAX_PATH + 1))  
  12.     {  
  13.         return false;  
  14.     }  
  15.   
  16.     // 获取Logic Drive String长度  
  17.     UINT uiLen = GetLogicalDriveStrings(0, NULL);  
  18.     if (0 == uiLen)  
  19.     {  
  20.         return false;  
  21.     }  
  22.   
  23.     PTSTR pLogicDriveString = new TCHAR[uiLen + 1];  
  24.     ZeroMemory(pLogicDriveString, uiLen + 1);  
  25.     uiLen = GetLogicalDriveStrings(uiLen, pLogicDriveString);  
  26.     if (0 == uiLen)  
  27.     {  
  28.         delete[]pLogicDriveString;  
  29.         return false;  
  30.     }  
  31.   
  32.     TCHAR szDrive[3] = TEXT(" :");  
  33.     PTSTR pDosDriveName = new TCHAR[MAX_PATH];  
  34.     PTSTR pLogicIndex = pLogicDriveString;  
  35.   
  36.     do  
  37.     {  
  38.         szDrive[0] = *pLogicIndex;  
  39.         uiLen = QueryDosDevice(szDrive, pDosDriveName, MAX_PATH);  
  40.         if (0 == uiLen)  
  41.         {  
  42.             if (ERROR_INSUFFICIENT_BUFFER != GetLastError())  
  43.             {  
  44.                 break;  
  45.             }  
  46.   
  47.             delete[]pDosDriveName;  
  48.             pDosDriveName = new TCHAR[uiLen + 1];  
  49.             uiLen = QueryDosDevice(szDrive, pDosDriveName, uiLen + 1);  
  50.             if (0 == uiLen)  
  51.             {  
  52.                 break;  
  53.             }  
  54.         }  
  55.   
  56.         uiLen = _tcslen(pDosDriveName);  
  57.         if (0 == _tcsnicmp(tsFileDosPath, pDosDriveName, uiLen))  
  58.         {  
  59.             wchar_t buf[1024];  
  60.             swprintf_s(buf, 1024, L"%s%s", szDrive, tsFileDosPath + uiLen);  
  61.             wchar_t *pstr = buf;  
  62.             szFilePath = std::wstring(pstr);  
  63.   
  64.             break;  
  65.         }  
  66.   
  67.         while (*pLogicIndex++);  
  68.     } while (*pLogicIndex);  
  69.   
  70.     delete[]pLogicDriveString;  
  71.     delete[]pDosDriveName;  
  72.   
  73.     return true;  
  74. }  

china_jeffery CSDN认证博客专家 C/C++ Qt Node.js
持续学习者;
擅长开发开源组件及相关工具;
长期致力于应用各种IT新技术提升生产效率和解决实际问题;
china_jeffery@163#com
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值