方法1 定位某個進程(比如 QQMusic.exe)所在的全路徑,下面是代碼:
string GetProcessInfo(HANDLE hProcess,char* processName)
{
PROCESSENTRY32* pinfo = new PROCESSENTRY32; //進程信息 (pinfo->dwSize = sizeof(PROCESSENTRY32);)
MODULEENTRY32* minfo = new MODULEENTRY32; //模塊信息 (minfo->dwSize = sizeof(MODULEENTRY32);)
char shortpath[MAX_PATH]; //保存路徑變量
int flag = Process32First(hProcess,pinfo); // 從第一個進程開始
while(flag){
// 如果是 QQMusic.exe 這個進程
if(strcmp(pinfo->szExeFile, processName) == 0){
// 創建進程快照
HANDLE hModule = CreateToolhelp32Snapshot(
TH32CS_SNAPMODULE, //(DWORD) 快照返回的對象,TH32CS_SNAPMODULE 是指 "特定進程的使用模塊的列表"
pinfo->th32ProcessID //(DWORD) 要獲取快照進程的PID,當前進程/系統列表 快照時設為0
);
// 把第一個模塊信息給 minfo
Module32First(
hModule, //(HANDLE) CreateToolhelp32Snapshot 的返回句柄
minfo // (LPMODULEENTRY32) 接收模塊信息
);
// 把文件路徑給 shortpath
GetShortPathName(
minfo->szExePath, // 文件路徑(但最好不要用這個,因為這個碰到中文會出現亂碼)
shortpath, // 用來接收 minfo->szExePath 兼容中文的值
256 // 緩沖區大小
);
return shortpath;
}
// 下一個進程
flag = Process32Next(hProcess, pinfo);
}
return NULL;
}
int main()
{
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); // 創建進程快照
PROCESSENTRY32 process = {sizeof(PROCESSENTRY32)}; // 用來接收 hProcessSnap 的信息
// 遍歷進程快照
while (Process32Next(hProcessSnap,&process)){
// 找到 QQMusic.exe 進程
string processName = process.szExeFile; // char* 轉 string
if(processName == "QQMusic.exe"){
string s_exePath = GetProcessInfo(hProcessSnap,"QQMusic.exe"); // 進程的全路徑
cout << s_exePath << endl;
break;
}
}
return 0;
}
方法2 第一種方法有些 bug,下面說下另一種方法
另一種方法:
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); // 創建進程快照
PROCESSENTRY32 process = {sizeof(PROCESSENTRY32)}; // 用來接收 hProcessSnap 的信息
// 遍歷進程快照
while (Process32Next(hProcessSnap,&process)){
// 獲取進程名
string processName = process.szExeFile;
cout << processName << endl;
// 獲取全路徑
char chpath[MAX_PATH];
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
GetModuleFileNameEx(hProcess,NULL,chpath,sizeof(chpath));
cout << chpath << endl;
cout << "-------------------" << endl;
}
但是注意,這種方法不能獲取路徑在 system32 的進程路徑,其余正常:
方法3(推薦) 目前沒有發現 Bug,無法讀取應用程序拒絕訪問的進程路徑,其他沒有問題。
// dos 文件路徑轉 windows 文件路徑
BOOL DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
{
TCHAR szDriveStr[500];
TCHAR szDrive[3];
TCHAR szDevName[100];
INT cchDevName;
INT i;
//檢查參數
if(!pszDosPath || !pszNtPath )
return FALSE;
//獲取本地磁盤字符串
if(GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
{
for(i = 0; szDriveStr[i]; i += 4)
{
if(!lstrcmpi(&(szDriveStr[i]), _T("A:\\")) || !lstrcmpi(&(szDriveStr[i]), _T("B:\\"))){continue;}
szDrive[0] = szDriveStr[i];
szDrive[1] = szDriveStr[i + 1];
szDrive[2] = '\0';
// 查詢 Dos 設備名
if(!QueryDosDevice(szDrive, szDevName, 100)){return FALSE;}
// 命中
cchDevName = lstrlen(szDevName);
if(_tcsnicmp(pszDosPath, szDevName, cchDevName) == 0){
// 復制驅動器
lstrcpy(pszNtPath, szDrive);
// 復制路徑
lstrcat(pszNtPath, pszDosPath + cchDevName);
return TRUE;
}
}
}
lstrcpy(pszNtPath, pszDosPath);
return FALSE;
}
// 獲取進程全路徑
BOOL GetProcessFullPath(DWORD dwPID,string &fullPath){
TCHAR szImagePath[MAX_PATH];
TCHAR pszFullPath[MAX_PATH];
HANDLE hProcess;
// 初始化失敗
if(!pszFullPath){return FALSE;}
pszFullPath[0] = '\0';
// 獲取進程句柄失敗
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID);
if(!hProcess){return FALSE;}
// 獲取進程完整路徑失敗
if(!GetProcessImageFileName(
hProcess, // 進程句柄
szImagePath, // 接收進程所屬文件全路徑的指針
MAX_PATH // 緩沖區大小
)){
CloseHandle(hProcess);
return FALSE;
}
// 路徑轉換失敗
if(!DosPathToNtPath(szImagePath, pszFullPath)){
CloseHandle(hProcess);
return FALSE;
}
CloseHandle(hProcess);
// 導出文件全路徑
fullPath = pszFullPath;
return TRUE;
}
調用例子:
tring str_filePath;
GetProcessFullPath(進程ID,str_filePath);