应使用PerfMon性能计数器“\Objects\Handle Count”,因其无需提权、稳定可靠;若需实时精确值,可选用NtQuerySystemInformation(Win10 1809前)或SYSTEM_HANDLE_INFORMATION_EX(之后),但需管理员权限并处理结构兼容性。

如果您需要在C++程序中实时获取Windows系统当前全局句柄引用总数,用于监控、统计或异常分析,则需调用Windows内核对象管理相关的未公开接口或替代机制。以下是实现该目标的多种可行路径:
一、使用NtQuerySystemInformation配合SYSTEM_HANDLE_INFORMATION
该方法通过调用ntdll.dll导出的NtQuerySystemInformation函数,请求类型为SystemHandleInformation,可枚举当前系统中所有进程持有的句柄信息,进而统计总数。此方式需以管理员权限运行,并处理结构体动态大小与版本兼容性问题。
1、加载ntdll.dll并获取NtQuerySystemInformation函数地址。
2、分配足够大的缓冲区(初始可设为64KB),循环调用NtQuerySystemInformation直至返回STATUS_SUCCESS。
立即学习“C++免费学习笔记(深入)”;
3、解析返回的SYSTEM_HANDLE_INFORMATION结构链表,逐个计数每个句柄条目。
4、累加所有进程的句柄数量,得到全局句柄引用总数。
5、注意:Windows 10 1809+版本中SYSTEM_HANDLE_INFORMATION已被弃用,应改用SYSTEM_HANDLE_INFORMATION_EX。
二、读取PerfMon性能计数器中的“Objects”计数器
Windows性能监视器(PerfMon)公开了名为“Objects”的性能对象,其“Handle Count”计数器直接反映系统当前句柄总数。该方式无需提权,稳定性高,适合生产环境长期监控。
1、调用PdhOpenQuery创建性能数据查询句柄。
2、使用PdhAddCounter添加全系统级计数器路径:“\Objects\Handle Count”。
3、调用PdhCollectQueryData触发一次数据采集。
4、调用PdhGetFormattedCounterValue获取64位整型结果值。
5、注意:该计数器值每秒刷新一次,非实时瞬时值,且需确保“Performance Logs and Alerts”服务已启用。
三、解析/proc/sys/kernel/handles(仅限WSL2 Linux内核环境)
当运行于WSL2且宿主为Windows 10/11时,若需在Linux子系统中获取等效句柄统计,可借助WSL2内核暴露的虚拟/proc接口。该路径不适用于原生Windows C++应用,但可用于跨平台监控代理场景。
1、在WSL2中执行open("/proc/sys/kernel/handles", O_RDONLY)打开句柄统计伪文件。
2、调用read()读取其内容,格式为“total: 124890 used: 45231 max: 16777216”。
3、使用sscanf解析total字段数值作为全局句柄引用总数。
4、注意:此路径仅在WSL2启用kernel.sysctl支持且内核版本≥5.10.60.1时可用,原生Windows不可用。
四、调用ZwQuerySystemInformation(内核模式驱动辅助)
在具备内核驱动开发能力的前提下,可通过用户态发送IOCTL至自定义驱动,由驱动调用ZwQuerySystemInformation(SystemExtendedHandleInformation)获取增强句柄信息,规避用户态结构体版本问题,并支持过滤与聚合。
1、编写WDM驱动,导出设备对象及IOCTL_CODE用于接收查询请求。
2、驱动中调用ZwQuerySystemInformation传入SystemExtendedHandleInformation类型。
3、遍历返回的SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX数组,按ObjectPointer字段去重统计有效句柄引用。
4、将统计结果通过IRP输出缓冲区返回至用户态应用程序。
5、注意:此方案需数字签名驱动且禁用Driver Signature Enforcement,仅限测试与专用安全监控场景。


















