You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++枚举Windows系统所有用户的全部进程?

你当前的代码无法枚举其他用户进程的核心原因有两个:

  • 默认运行的程序没有启用SeDebugPrivilege调试特权,无法跨用户获取其他安全上下文进程的句柄
  • OpenProcess请求了PROCESS_VM_READ权限,该权限需要很高的访问等级,普通上下文无法对系统/其他用户进程获取该权限,导致后续EnumProcessModules调用失败,返回未知进程名。
具体解决步骤

步骤1:为当前进程启用SeDebugPrivilege特权

在进程启动后、枚举进程前,调用以下代码调整令牌权限:

BOOL EnableDebugPrivilege() {
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
        return FALSE;
    }

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
        CloseHandle(hToken);
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
        CloseHandle(hToken);
        return FALSE;
    }

    CloseHandle(hToken);
    return GetLastError() == ERROR_SUCCESS;
}

注意:该操作需要程序以管理员身份运行才能成功,普通用户账户没有SeDebugPrivilege的分配权限

步骤2:优化OpenProcess权限与进程名获取逻辑

替换原有的高权限请求与EnumProcessModules逻辑,改用低权限即可调用的API获取进程名:

void PrintProcessNameAndID(DWORD processID) {
    TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
    // 改用低权限的PROCESS_QUERY_LIMITED_INFORMATION,Vista及以上系统支持
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processID);

    if (NULL != hProcess) {
        DWORD size = MAX_PATH;
        // 不需要读进程内存,直接调用API获取进程路径
        if (QueryFullProcessImageName(hProcess, 0, szProcessName, &size)) {
            // 可选:只保留文件名,去掉路径前缀
            TCHAR* pName = _tcsrchr(szProcessName, '\\');
            if (pName) {
                _tcscpy_s(szProcessName, MAX_PATH, pName + 1);
            }
        }
        CloseHandle(hProcess);
    }

    _tprintf(TEXT("%s  (PID: %u)\n"), szProcessName, processID);
}

步骤3:修改main函数,启动时先调用权限调整

在main函数最开头加入权限启用逻辑:

int main(void) {
    // 先启用调试特权
    if (!EnableDebugPrivilege()) {
        _tprintf(TEXT("警告:无法启用调试特权,可能无法枚举全部进程,请尝试以管理员身份运行\n"));
    }

    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;

    if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
        return 1;
    }

    cProcesses = cbNeeded / sizeof(DWORD);

    for (i = 0; i < cProcesses; i++) {
        if (aProcesses[i] != 0) {
            PrintProcessNameAndID(aProcesses[i]);
        }
    }

    return 0;
}
备选方案:使用Toolhelp32 API

如果你需要兼容更老的系统,也可以直接改用Toolhelp32系列API枚举进程,对权限要求更低,不需要额外调用OpenProcess即可获取进程名:

#include <tlhelp32.h>

void EnumProcessWithToolhelp() {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return;
    }

    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hSnapshot, &pe32)) {
        CloseHandle(hSnapshot);
        return;
    }

    do {
        _tprintf(TEXT("%s  (PID: %u)\n"), pe32.szExeFile, pe32.th32ProcessID);
    } while (Process32Next(hSnapshot, &pe32));

    CloseHandle(hSnapshot);
}

内容的提问来源于stack exchange,提问作者mrRobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:24:07