GetLogicalDrives()仅返回存在盘符的位掩码,不提供容量信息;需结合GetDriveType()筛选可用驱动器后,再对每个有效盘符(如"C:\")调用GetDiskFreeSpaceEx()获取总大小、可用及空闲空间。

GetLogicalDrives() 只能告诉你有哪些盘符,不能直接拿到容量
很多人以为 GetLogicalDrives() 返回的位掩码能顺带给出容量信息——它只返回一个 32 位整数,每位代表 A:~Z: 是否存在,比如返回 0x0000001D(二进制末5位为1),说明 C:、D:、E: 存在。但容量、可用空间、文件系统类型这些,它一概不提供。
真正要拿容量,得对每个有效盘符调用 GetDiskFreeSpaceEx()。这个函数会填入总大小、可用字节数、空闲字节数三个值,注意:它返回的是 ULARGE_INTEGER,不是简单 int64_t,直接取 .QuadPart 才安全。
- 必须先用
GetLogicalDrives()筛出真实存在的驱动器,否则对不存在的盘符(如 A:)调用GetDiskFreeSpaceEx()会失败,GetLastError()返回ERROR_NOT_READY - 盘符字符串格式必须是
"C:\\"(双反斜杠结尾),不是"C:"或"C:\"—— 后者可能被某些 Windows 版本拒绝 -
GetDiskFreeSpaceEx()不支持网络驱动器映射路径(如"Z:\some\share"),只认根路径,且要求路径存在并可访问
用 GetDriveType() 过滤掉无效或不可用的驱动器
即使 GetLogicalDrives() 报告某盘符存在,也不代表它当前可用。比如光驱没放盘、U 盘被拔出、网络驱动器断连,GetDiskFreeSpaceEx() 就会失败。这时候靠 GetDriveType() 提前判断更稳妥。
它返回整型常量,常见值有:DRIVE_FIXED(本地硬盘)、DRIVE_REMOVABLE(U 盘/SD 卡)、DRIVE_REMOTE(网络驱动器)、DRIVE_NO_ROOT_DIR(路径无效)、DRIVE_CDROM(光驱)。只有返回前三种才值得继续查容量。
-
GetDriveType("A:\")在多数现代系统上返回DRIVE_REMOVABLE,但若软驱已移除或禁用,也可能返回DRIVE_NO_ROOT_DIR - 对网络驱动器(
DRIVE_REMOTE),GetDiskFreeSpaceEx()可能成功也可能超时失败,取决于连接状态;建议加SetThreadExecutionState(ES_CONTINUOUS)避免休眠中断查询 - 不要跳过
GetDriveType()直接硬查——频繁对不可用驱动器调用GetDiskFreeSpaceEx()会导致明显卡顿,尤其在旧设备上
注意单位换算和大数处理:别用 int64_t 直接接收 ULARGE_INTEGER
ULARGE_INTEGER 是联合体,包含 QuadPart(LONGLONG)和两个 DWORD 成员。虽然 QuadPart 本质是 64 位有符号整数,但磁盘容量永远 ≥ 0,所以实际用 ULONGLONG 更准确。如果强行用 int64_t 接收,遇到超过 2^63 字节(约 9EB)的存储设备(如未来 NAS 阵列),高位会被误解释为负数。
示例片段:
ULARGE_INTEGER total, free, avail;
if (GetDiskFreeSpaceEx(L"C:\", &total, &avail, &free)) {
ULONGLONG totalBytes = total.QuadPart; // 正确
// int64_t wrong = total.QuadPart; // 错误:语义不符,且可能溢出显示
}
- 打印时用
%I64u(Windows)或"%" PRIu64(C++11+,需) - 转换为 GB 要除以
1024ULL * 1024ULL * 1024ULL,别漏ULL后缀,否则中间计算可能溢出成int - NTFS 压缩卷、ReFS 池等特殊卷,
GetDiskFreeSpaceEx()返回的是逻辑空间,不是物理占用——这点和资源管理器显示一致,无需额外处理
Unicode 路径和权限:WideChar 版本是唯一可靠选择
Windows API 的 ANSI 版本(如 GetLogicalDrivesA())在非英文系统下可能无法正确识别含 Unicode 字符的卷标(虽然盘符本身是 ASCII),而且从 Windows Vista 起,很多系统级路径(如 "C:\$Recycle.Bin")默认只允许 WideChar 访问。所以必须用宽字符版本:全部函数名加 W 后缀,字符串用 L"..."。
- 项目设置里必须定义
UNICODE和_UNICODE,否则TEXT()宏会展开成 ANSI,导致链接失败 - 不需要管理员权限就能调用这些函数——哪怕对
C:\查询,也只要用户有读取卷信息的权限(默认都有) - 如果程序在沙盒环境(如 Windows AppContainer)中运行,
GetDiskFreeSpaceEx()对系统卷可能返回 0,这是策略限制,不是代码问题
实际跑起来最常卡住的地方,是忘了给盘符加双反斜杠后缀,或者把 GetDriveType() 的结果当成布尔值直接用。这两个点不试错一遍很难记住。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










