可采用四种方法获取当前进程句柄总数:一、调用NtQuerySystemInformation遍历系统句柄表筛选目标进程;二、通过PDH API查询“ProcessHandle Count”性能计数器;三、利用NtQueryObject与ZwDuplicateObject枚举对象类型并复制句柄统计;四、Windows 10 1809+支持CreateToolhelp32Snapshot(TH32CS_SNAPHANDLE)直接快照句柄表。

如果您需要在 C++ 程序中实时获取当前进程所持有的全局句柄引用总数,以支持进程资源监控场景,则需借助 Windows 平台特定的系统 API 和性能计数器机制。以下是实现该目标的多种可行方法:
一、使用 NtQuerySystemInformation 获取句柄表信息
该方法通过调用未公开但广泛使用的 NT 内核函数 NtQuerySystemInformation,传入 SystemHandleInformation 类型参数,遍历系统中所有进程的句柄表条目,并筛选出目标进程的句柄数量。需注意此接口无官方文档支持,且结构体定义随系统版本变化。
1、包含必要头文件与类型定义,声明 NtQuerySystemInformation 函数指针。
2、调用 ZwQuerySystemInformation(或 NtQuerySystemInformation)并分配足够大的缓冲区接收 SYSTEM_HANDLE_INFORMATION 结构数组。
3、遍历返回的句柄信息列表,比对每个条目的 ProcessId 字段是否等于当前进程 ID(GetCurrentProcessId())。
4、统计匹配项数量,即为当前进程的句柄引用总数。
5、释放缓冲区内存并处理 STATUS_INFO_LENGTH_MISMATCH 重试逻辑。
二、通过 Performance Data Helper (PDH) 查询 _Handle Count 计数器
该方法利用 Windows 性能数据帮助器(PDH)API 访问内建的“Process”性能对象中的“Handle Count”计数器,适用于稳定、无需特权、可跨会话采集的监控场景。
1、调用 PdhOpenQuery 创建一个空的性能查询句柄。
2、构造完整路径字符串:\Process(YourProcessName)\Handle Count,其中 YourProcessName 可替换为 “explorer” 或使用 GetCurrentProcess() 配合 GetProcessImageFileName 获取实际名称。
3、调用 PdhAddCounter 将上述路径添加至查询句柄中。
4、执行 PdhCollectQueryData 触发一次数据采集。
5、调用 PdhGetFormattedCounterValue 获取 DWORD 类型的句柄计数值。
三、读取 NtQueryObject 返回的 ObjectTypesInformation 中的句柄统计
该方法通过 NtQueryObject 查询当前进程的句柄对象类型信息,再结合 ZwDuplicateObject 复制句柄并枚举其属性,间接推导句柄总数。适用于需区分句柄类型(如 Event、Section、Mutant)的深度监控需求。
1、使用 OpenProcess 打开当前进程,获取 PROCESS_DUP_HANDLE 权限句柄。
2、循环调用 NtQueryObject 并传入 ObjectTypesInformation 类型,获取系统已注册的对象类型列表。
3、对每种对象类型,尝试使用 ZwDuplicateObject 枚举当前进程所有可能句柄索引(0 至预估上限),捕获 STATUS_INVALID_HANDLE 错误作为终止条件。
4、累计成功复制的句柄数量,即为近似句柄引用总数。
5、关闭所有临时复制的句柄,防止泄漏。
四、使用 Toolhelp32Snapshot 枚举句柄(仅限 Windows 10 1809+)
自 Windows 10 版本 1809 起,CreateToolhelp32Snapshot 支持 TH32CS_SNAPHANDLE 标志,允许直接快照当前进程句柄表,是目前最轻量且受支持的公开接口方案。
1、调用 CreateToolhelp32Snapshot 并指定 dwFlags = TH32CS_SNAPHANDLE 和 th32ProcessID = GetCurrentProcessId()。
2、检查返回句柄是否有效,若为 INVALID_HANDLE_VALUE 则说明系统不支持该标志。
3、使用 Handle32First/Handle32Next 遍历所有 HANDLEENTRY32 结构体实例。
4、每成功获取一条记录,递增计数器;当返回 FALSE 且 GetLastError() != ERROR_NO_MORE_FILES 时停止。
5、调用 CloseHandle 关闭快照句柄。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











