DriveInfo 是获取磁盘总空间和可用空间最稳妥方式,需检查 IsReady 属性避免异常,AvailableFreeSpace 返回当前用户可写空间,单位字节需转换,.NET 6+ 已修复 ReFS/BitLocker 兼容问题。

用 DriveInfo 获取磁盘总空间和可用空间
直接用 DriveInfo 是最稳妥的方式,它不依赖 WMI 或外部命令,跨 .NET Framework / .NET Core / .NET 5+ 都能跑。关键点是:必须确保驱动器存在且可访问,否则构造 DriveInfo 实例时会抛 IOException 或 UnauthorizedAccessException。
- 用
DriveInfo.GetDrives()列出所有逻辑驱动器,再逐个检查IsReady属性——U 盘拔掉、光驱无盘、网络驱动器断开时,IsReady == false,此时读TotalSize或AvailableFreeSpace会直接异常 -
AvailableFreeSpace返回的是“当前用户有权限写入的剩余空间”,不是系统总空闲空间;如果需要管理员视角的空闲量(比如判断能否写入大文件),得用TotalFreeSpace(但该值在某些 NTFS 配额或磁盘配额启用时可能不准) - 单位全是字节,别忘了除以
1024.0 * 1024.0转 MB,避免整除丢精度
var drive = new DriveInfo("C:\");
if (drive.IsReady)
{
long total = drive.TotalSize; // 总容量
long free = drive.AvailableFreeSpace; // 当前用户可用空间
}为什么 GetDiskFreeSpaceEx 在 .NET 6+ 里不推荐直接调用
虽然 Win32 API GetDiskFreeSpaceEx 看起来更底层、更“准”,但在现代 .NET 中没必要手动 P/Invoke。原因很实在:
-
DriveInfo内部就是调的这个 API,你手动调只是重复造轮子,还多了异常处理和平台兼容性负担 - .NET 6+ 的
DriveInfo已修复了旧版本中对 ReFS 卷或 BitLocker 加密卷返回0的 bug - 若真要绕过
DriveInfo(比如需要获取lpTotalNumberOfFreeBytes这种原始字段),必须注意:API 返回的是ulong,而旧版 .NET Framework 的DriveInfo.TotalSize是long,超 8EB 的卷会溢出——不过目前 Windows 不支持这么大卷,纯理论风险
监控磁盘空间变化时,别用轮询 DriveInfo
想做“剩余空间低于 1GB 就告警”?别写个 while(true) { Thread.Sleep(5000); check(); }。问题很明显:
- CPU 白耗,尤其多驱动器时频繁构造
DriveInfo对象有开销 - 无法感知实时变化:U 盘热插拔、磁盘配额策略变更、BitLocker 解密进度等,轮询间隔内全漏掉
- 正确做法是监听 WMI 的
Win32_VolumeChangeEvent(需引用System.Management),或用FileSystemWatcher监控特定路径的写入行为间接推断——但后者不精确,仅适合粗粒度场景
UnauthorizedAccessException 出现时该怎么处理
常见于访问系统保留卷(如恢复分区、EFI 系统分区)或权限受限的网络驱动器。这不是代码写错了,而是运行环境限制:
- 捕获
UnauthorizedAccessException后,跳过该驱动器即可,不要重试或弹窗报错——用户通常没权限也没必要管这些卷 - 不要试图用
WindowsIdentity.GetCurrent().Impersonate()提权,这在 .NET Core+ 里不可用,且提权本身违反最小权限原则 - 如果业务强依赖某网络驱动器空间,应提前用
Directory.Exists()或File.OpenRead()做探针,失败则走降级逻辑(比如提示“目标位置不可用,请检查连接”)
真正麻烦的是那些挂载了但 IsReady == true、读属性却卡住几秒才抛异常的情况——建议加超时:用 Task.Run(() => drive.TotalSize).Wait(200) 包一层,超时就放弃。


















