推荐使用PDH性能计数器API读取“Process(_Total)Handle Count”,因其无需管理员权限、稳定兼容且实现简单;若需高精度则选用NtQuerySystemInformation,但须管理员权限并处理版本差异。

如果您需要在C++程序中实时获取Windows系统当前全局句柄引用总数,用于监控、统计或异常分析,则需调用Windows内核提供的性能计数器接口或NtQuerySystemInformation等底层机制。以下是实现该目标的多种可行方法:
一、使用PDH性能计数器API读取“Process(_Total)Handle Count”
该方法通过Windows性能数据帮助器(PDH)库访问系统内置的性能计数器,其中“Process(_Total)Handle Count”直接反映当前系统所有进程持有的句柄总数,无需管理员权限,稳定且兼容性好。
1、包含头文件:#include
2、调用PdhOpenQuery(nullptr, 0, &hQuery)初始化查询句柄。
立即学习“C++免费学习笔记(深入)”;
3、调用PdhAddCounter(hQuery, L"\Process(_Total)\Handle Count", 0, &hCounter)添加计数器。
4、调用PdhCollectQueryData(hQuery)触发一次数据采集。
5、调用PdhGetFormattedCounterValue(hCounter, PDH_FMT_LONG, nullptr, &counterValue)获取长整型结果值。
6、调用PdhCloseQuery(hQuery)释放资源。
注意:此计数器返回的是近似值,存在约1–2秒延迟,但对监控场景已足够精确。
二、调用NtQuerySystemInformation枚举SYSTEM_HANDLE_INFORMATION_EX
该方法直接调用未公开的ntdll.dll导出函数NtQuerySystemInformation,传入SystemHandleInformation或SystemHandleInformationEx信息类,可获取全系统句柄表快照,再遍历统计总数。精度最高,但需启用SeDebugPrivilege权限,且结构体定义随Windows版本变化。
1、使用OpenProcessToken和AdjustTokenPrivileges启用SeDebugPrivilege特权。
2、通过GetProcAddress从ntdll.dll获取NtQuerySystemInformation函数地址。
3、首次调用时传入nullptr与0,获取所需缓冲区大小。
4、分配足够大的内存缓冲区(通常需64KB以上),再次调用NtQuerySystemInformation填充数据。
5、根据Windows版本判断结构体布局:若为Win10 1809+,使用SYSTEM_HANDLE_INFORMATION_EX;否则回退至SYSTEM_HANDLE_INFORMATION。
6、遍历结构体数组,累加句柄数量字段(如NumberOfHandles或HandleCount)。
注意:必须以管理员权限运行,且在Windows Server Core或某些精简版系统上可能被禁用。
三、解析PerfMon共享内存映射节(_PerfData)
Windows性能监视器将实时计数器数据映射到命名共享内存节“\BaseNamedObjects\_PerfData”,其中包含完整性能对象树。通过映射该节并解析其二进制结构,可定位“Process”对象下的“Handle Count”实例索引并读取数值,绕过PDH层开销。
1、调用CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READONLY, 0, 0, L"\BaseNamedObjects\_PerfData")打开映射节。
2、调用MapViewOfFile获取基地址,并验证签名(如PERF_DATA_BLOCK结构Magic成员是否为0x00000100)。
3、按PERF_DATA_BLOCK → PERF_OBJECT_TYPE → PERF_COUNTER_BLOCK顺序偏移遍历,查找ObjectNameTitleIndex为“Process”且CounterNameTitleIndex为“Handle Count”的计数器项。
4、定位到对应PERF_INSTANCE_DEFINITION后,读取其后的LONG型计数值(偏移量依赖CounterSize与CounterOffset)。
5、调用UnmapViewOfFile和CloseHandle清理资源。
注意:该方式不依赖外部DLL,但结构解析极易因Windows更新失效,仅建议用于离线分析工具。
四、通过WMI查询Win32_PerfFormattedData_PerfOS_Processor的衍生指标
虽然WMI无直接暴露全局句柄总数的类,但可通过Win32_PerfRawData_PerfProc_Process类聚合所有进程的HandleCount属性求和,再转换为格式化值。适用于跨平台管理脚本集成场景,但性能开销大、延迟高。
1、初始化COM库:CoInitializeEx(nullptr, COINIT_MULTITHREADED)。
2、连接WMI命名空间:CoCreateInstance + IWbemLocator::ConnectServer(L"root\cimv2")。
3、设置安全上下文:IWbemServices::SetSecurityBlanket。
4、执行WQL查询:"SELECT HandleCount FROM Win32_PerfRawData_PerfProc_Process WHERE Name != '_Total'"。
5、遍历IWbemClassObject结果集,提取HandleCount属性并累加。
6、释放IWbemServices、IWbemLocator及COM资源。
注意:每次查询耗时约150–400ms,不适用于高频采样(如。


















