本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/47746621
上两篇中,我们讲到了ToolHelp API,Process API和提升Debug权限,这一篇中来说说如何获取进程的程序路径。
获取进程路径其实有很多方法。
方法1。使用ToolHelp API枚举模块,其中,Module32First得到一个MODULEENTRY32 结构,结构中有一个szExePath成员,这个成员代表这个进程第一个模块的路径,也就是进程的路径
(32位程序只能获取32位程序路径,64位程序可以获取32位和64位程序路径,但需要把TH32CS_SNAPMODULE换成TH32CS_SNAPMODULE32)
方法2。使用OpenProcess打开进程,需要具有PROCESS_QUERY_INFORMATION 和 PROCESS_VM_READ权限,然后用EnumProcessModules获取第一个模块的模块句柄,之后用GetModuleFileNameEx获取模块路径。
EnumProcessModules的模块句柄无需释放:Do not call CloseHandle on any of the handles returned by this function. The information comes from a snapshot, so there are no resources to be freed.
(32位程序只能获取32位程序路径,64位程序只能获取64位程序路径)
完整源码:
#define PSAPI_VERSION 1
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
// 获取进程路径 参数1:进程ID 参数2:缓冲区指针,接收路径
void GetProcessPath(DWORD dwProcessID, LPCTSTR buffer)
{
TCHAR Filename[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
if (hProcess == NULL)return;
HMODULE hModule;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded))
{
if (GetModuleFileNameEx(hProcess, hModule, Filename, MAX_PATH)){
RtlMoveMemory((void*)buffer, Filename, sizeof(TCHAR)*MAX_PATH);
}
}
CloseHandle(hProcess);
}
方法3。使用GetProcessImageFileName,可以在32位程序中获取32位和64位进程路径,这个可以在xp和以后系统中用,但是取得的进程路径是设备名路径,所以还需要遍历磁盘驱动器转换成我们需要的路径,比较麻烦。
方法4。使用QueryFullProcessImageName,可以在32位程序中获取32位和64位进程路径,同时这也是微软提供的32位程序获取64位进程路径的正确方法,缺点是只能在Vista以后的系统中用
BOOL WINAPI QueryFullProcessImageName(
_In_ HANDLE hProcess,
_In_ DWORD dwFlags,
_Out_ LPTSTR lpExeName,
_Inout_ PDWORD lpdwSize
);
hProcess:进程句柄,需要具有PROCESS_QUERY_INFORMATION或者PROCESS_QUERY_LIMITED_INFORMATION权限
dwFlags:以下值
0:名称应使用 Win32 路径格式。
PROCESS_NAME_NATIVE:名称应使用原生系统路径格式
lpExeName:缓冲区指针,用于接收可执行映像的路径
lpdwSize:以字符为单位指定缓冲区大小的 lpExeName,不包括空终止字符的数
返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。
不过感觉这个函数忒难用,,那么加上这个函数,GetModuleFileNameEx获取不了的就用QueryFullProcessImageName,那么GetProcessPath就成这样的了:
// 获取进程路径 参数1:进程ID 参数2:缓冲区指针,接收路径
void GetProcessPath(DWORD dwProcessID, LPCTSTR buffer)
{
TCHAR Filename[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
if (hProcess == NULL)return;
HMODULE hModule;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded))
{
if (GetModuleFileNameEx(hProcess, hModule, Filename, MAX_PATH)){
RtlMoveMemory((void*)buffer, Filename, sizeof(TCHAR)*MAX_PATH);
}
}
else{
DWORD size = MAX_PATH;
if (QueryFullProcessImageName(hProcess, 0, Filename, &size)){
RtlMoveMemory((void*)buffer, Filename, sizeof(TCHAR)*MAX_PATH);
}
}
CloseHandle(hProcess);
}
这样绝大部分进程都可以获取路径了,有几个系统进程(比如services.exe)进程即使以Debug也无法打开获取句柄,因此无法获取路径