最直接可靠的方式是枚举A:–Z:驱动器字母,对每个拼出如L"C:\"的宽字符路径调用GetDiskFreeSpaceExW;需先用GetLogicalDrives()筛选有效驱动器,跳过ERROR_NOT_READY等失败情况,优先用lpAvailableBytes显示用户空间,备份预估则参考lpFreeBytesAvailable,并通过GetVolumeInformation区分NTFS/ReFS预留差异。

用 GetDiskFreeSpaceEx 遍历所有驱动器字母
Windows 下最直接可靠的方式是枚举所有可能的驱动器字母(A:–Z:),对每个有效挂载点调用 GetDiskFreeSpaceEx。它返回的是真实的总空间、可用空间(含管理员预留)、以及实际空闲空间(不含预留),比 GetDiskFreeSpace 更准确。
常见错误是只查 GetLogicalDrives() 返回的位掩码,却没跳过未挂载或无效的盘符(比如光驱插着但无盘、网络驱动器离线)——这会导致 GetDiskFreeSpaceEx 失败,但不报错,而是返回 0 值,容易误判为“空间为 0”。
- 先用
GetLogicalDrives()获取哪些字母被系统识别为逻辑驱动器 - 对每个字母拼出路径如
"C:\"(注意双反斜杠),再调用GetDiskFreeSpaceEx - 检查返回值:失败时
GetLastError()通常为ERROR_NOT_READY或ERROR_INVALID_DRIVE,此时跳过 - 不要依赖
lpFreeBytesAvailable做用户可见的“剩余空间”,它受磁盘配额和管理员预留影响;一般用lpFreeBytesAvailable(含预留)还是lpAvailableBytes(不含预留)得看用途:显示给用户建议用lpAvailableBytes,做容量预警可参考lpFreeBytesAvailable
区分 NTFS 和 ReFS 等卷类型带来的精度差异
GetDiskFreeSpaceEx 对所有 Windows 卷都适用,但不同文件系统对“可用空间”的定义略有出入。NTFS 默认保留约 1/8 总空间给管理员(可通过 fsutil behavior set DisableLastAccess 1 类似命令间接影响,但不推荐动),而 ReFS 在 Server 2022+ 中默认关闭该预留。这意味着同一块物理盘,NTFS 卷的 lpFreeBytesAvailable 可能比 lpAvailableBytes 少几个 GB。
如果你在做备份空间预估,别只看 lpAvailableBytes;如果在写磁盘健康监控工具,建议同时记录 lpTotalNumberOfBytes - lpFreeBytesAvailable,这个差值能反映预留/隐藏占用量变化趋势。
立即学习“C++免费学习笔记(深入)”;
- 用
GetVolumeInformation查lpFileSystemNameBuffer判断卷类型,比如返回"NTFS"或"ReFS" - NTFS 卷上,
lpFreeBytesAvailable≈lpAvailableBytes+ 约 12.5% ×lpTotalNumberOfBytes(非绝对,取决于格式化参数) - 不要用
GetDiskFreeSpaceEx查网络驱动器(如 Z: 映射到 \servershare)——它返回的是服务器端卷信息,不是本地缓存视图
避免 Unicode 路径导致的 GetDiskFreeSpaceExW 调用失败
必须用宽字符版本 GetDiskFreeSpaceExW,传入 L"C:\\" 这样的 LPCWSTR。如果误用 ANSI 版本 GetDiskFreeSpaceExA,在路径含非 ASCII 字符(比如中文卷标)时会静默失败,返回 0 —— 而且不会触发异常,只会让后续计算崩掉。
另一个坑是路径末尾漏掉反斜杠:传 L"C:" 不等于 L"C:\"。GetDiskFreeSpaceEx 要求是“根目录路径”,L"C:" 在某些上下文里会被解释为“当前 C: 下的工作目录”,结果不可控。
- 始终使用
GetDiskFreeSpaceExW,链接时确保UNICODE宏已定义 - 驱动器字符串务必拼成
std::wstring(L"X:\")格式,不能是L"X:"或L"X:/ - 测试时手动给某个分区设中文卷标(如
ren D: 新数据盘),再运行程序,确认是否仍能读出数值
性能与权限:为什么不用 WMI 或 PowerShell 替代
有人想用 Win32_Volume WMI 查询,或者跑 powershell -c "Get-PSDrive" 再解析,看似更“高级”,实则三倍慢、易卡住、还依赖 COM 初始化或 PowerShell 运行时。而 GetDiskFreeSpaceExW 是纯 kernel32 调用,平均耗时
唯一权限相关问题是:若某卷启用了 BitLocker 且处于锁定状态,GetDiskFreeSpaceExW 会失败(ERROR_ACCESS_DENIED)。这不是 bug,是设计使然——未解锁的加密卷对大多数 API 来说就是“不可见设备”。这时候你只能跳过,不能强行绕过。
- 单次遍历 A:–Z: 最多 26 次调用,总开销可忽略,无需缓存或异步
- 不需要管理员权限,普通用户进程即可获取所有已挂载卷的空间数据
- 遇到
ERROR_ACCESS_DENIED(比如 BitLocker 锁定卷、EFS 加密卷未登录)就跳过,别重试或弹窗提示——用户知道该去解锁
事情说清了就结束。真正难的不是调哪个函数,而是怎么把“C:”这种字符串拼对、怎么区分 0 是真没空间还是调用失败、以及看到 lpFreeBytesAvailable 比 lpAvailableBytes 小几十个 G 时别慌。



















