方法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;
}

C++ 获取进程所在目录(全路径)_文件路径

方法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 的进程路径,其余正常:

C++ 获取进程所在目录(全路径)_C/C++ 基础知识_02

方法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);

版权声明:本博客文章与代码均为学习时整理的笔记,文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!