不能。Windows API 未导出 GetProcessHandleCount 函数,用户态程序无法直接调用;可靠方式仅有 NtQueryInformationProcess(推荐,需手动加载 ntdll.dll 并传入 64)或 EnumProcessHandles 枚举计数。

GetProcessHandleCount 能直接拿到句柄数吗?
不能。Windows API 没有导出 GetProcessHandleCount 这个函数——它只存在于内核符号里,用户态程序无法直接调用。你查文档或搜到的同名函数,基本是误传或混淆了内核调试接口。
真正可用、稳定、无需管理员权限的方式只有两个:NtQueryInformationProcess(需手动加载 ntdll.dll)或 GetProcessHandleCount 的替代方案:通过 EnumProcessHandles(PSAPI + Toolhelp32)逐个枚举再计数。前者快但略底层;后者慢但兼容性好、无需额外权限。
- 优先用
NtQueryInformationProcess+ProcessHandleCount类型(值为 64),这是最轻量级的获取方式 - 如果目标进程是 32 位而你的程序是 64 位(或反之),
EnumProcessHandles可能失败或漏数,此时必须用NtQueryInformationProcess - 注意:该 API 返回的是「当前时刻」的句柄数,不是峰值,也不是内核对象引用计数
用 NtQueryInformationProcess 获取句柄数的最小可行代码
你需要手动声明函数签名并从 ntdll.dll 中获取地址。Windows SDK 不公开此函数,所以不能直接链接 ntdll.lib。
HANDLE hProcess = GetCurrentProcess();
typedef NTSTATUS (NTAPI *pfnNtQueryInformationProcess)(
HANDLE, UINT, PVOID, ULONG, PULONG);
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
pfnNtQueryInformationProcess pNtQueryInfo =
(pfnNtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess");
DWORD handleCount = 0;
NTSTATUS status = pNtQueryInfo(
hProcess,
64, // ProcessHandleCount
&handleCount,
sizeof(DWORD),
nullptr
);
if (NT_SUCCESS(status)) {
printf("Handle count: %u\n", handleCount);
}
-
64是硬编码的ProcessHandleCount常量(定义在 WDK 中,用户头文件不暴露) - 返回值是
NTSTATUS,不是 Win32 错误码,别用GetLastError()判断失败 - 某些旧版 Windows(如 XP SP2)可能不支持该信息类,建议加
NT_SUCCESS(status)容错
句柄泄露排查时,为什么光看总数不够?
句柄总数稳定在 200 并不意味着没泄露——可能泄漏的是 EVENT、MUTANT 或 Section 这类生命周期长的对象,而 FILE 或 Thread 句柄被快速复用掩盖了问题。
直播话术巡检系统(Windows版) — 实时语音转写、关键词检测、场景自动切换、告警推送、大屏可视化。支持 Windows VB-Cable 虚拟声卡音频采集,阿里云 ASR 实时识别。一键启动脚本,自动安装环境。
- 用
Process Explorer(Sysinternals)按「Handle Type」排序,重点关注数量异常增长的类型 - 在代码中对关键句柄做
SetHandleInformation(h, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0)后打日志,可辅助定位未关闭点 - 启用应用验证器(Application Verifier)+ 「Handle」选项,它会在句柄分配/关闭时记录堆栈,但仅限调试环境且会显著拖慢运行速度
- Release 版本中,可在
CloseHandle失败时记录GetLastError()==ERROR_INVALID_HANDLE,这往往说明提前关闭或重复关闭
EnumProcessHandles 枚举时常见的坑
这个方法依赖 Psapi.dll 和 Toolhelp32,看似“标准”,实则陷阱密集:
- 必须以
PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE权限打开目标进程,否则EnumProcessHandles直接返回FALSE - 即使你查的是自己进程(
GetCurrentProcess()),也得用OpenProcess重新打开一次,因为GetCurrentProcess()返回的伪句柄不支持句柄枚举 - 枚举结果不含句柄属性(如是否可继承、是否被保护),也无法区分是哪个线程创建的,对多线程泄漏定位帮助有限
- 在 Windows 10 1809+ 上,部分句柄(如某些内核驱动创建的)会被过滤掉,导致计数偏少
真实排查中,句柄数只是起点。更关键的是:泄漏是否随特定操作线性增长?是否与某次 CreateEvent / CreateFile 调用一一对应?这些比数字本身重要得多。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










