System.IO.DriveInfo 是 .NET Framework 2.0 引入的類別,提供存取磁碟機資訊的標準化方式,包括磁碟機類型、格式化式、總容量、可用空間、磁碟標籤等。本文完整解析 DriveInfo 用法、常見陷阱、跨平台差異與磁碟監控實作模式。
| 屬性 | 型別 | 說明 | 單位/備註 |
|---|---|---|---|
| Name | string | 磁碟機根目錄路徑 | 如 "C:\\" |
| DriveType | DriveType | 磁碟機類型枚舉 | Fixed、Removable、Network、CDRom、Ram、Unknown |
| DriveFormat | string | 檔案系統格式 | NTFS、FAT32、exFAT、ReFS |
| IsReady | bool | 磁碟機是否就緒可讀取 | 光碟機無媒體、網路磁碟離線時為 false |
| TotalSize | long | 總容量 | 位元組 |
| TotalFreeSpace | long | 總可用空間 (含配額限制) | 位元組 |
| AvailableFreeSpace | long | 當前使用者可用空間 | 位元組,受磁碟配額影響 |
| VolumeLabel | string | 磁碟區標籤 | 可讀寫 (需權限) |
| RootDirectory | DirectoryInfo | 根目錄資訊 | 可進一步列舉檔案 |
using System;
using System.IO;
public static void ListAllDrives()
{
DriveInfo[] drives = DriveInfo.GetDrives();
Console.WriteLine($"{"磁碟機",-10} {"類型",-12} {"格式",-8} {"總容量",-15} {"可用空間",-15} {"標籤"}");
Console.WriteLine(new string('-', 80));
foreach (DriveInfo drive in drives)
{
Console.Write($"{drive.Name,-10} {drive.DriveType,-12} ");
if (drive.IsReady)
{
Console.Write($"{drive.DriveFormat,-8} ");
Console.Write($"{FormatBytes(drive.TotalSize),-15} ");
Console.Write($"{FormatBytes(drive.AvailableFreeSpace),-15} ");
Console.Write($"{drive.VolumeLabel}");
}
else
{
Console.Write("[未就緒/無媒體]");
}
Console.WriteLine();
}
}
static string FormatBytes(long bytes)
{
string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB" };
int i = 0;
double value = bytes;
while (value >= 1024 && i < suffixes.Length - 1)
{
value /= 1024;
i++;
}
return $"{value:0.##} {suffixes[i]}";
}
public static DriveInfo GetDriveInfo(string path)
{
// 可傳入任意路徑,自動解析所在磁碟機
DriveInfo drive = new DriveInfo(Path.GetPathRoot(path));
if (!drive.IsReady)
throw new IOException($"磁碟機 {drive.Name} 未就緒");
return drive;
}
// 使用
var cDrive = GetDriveInfo(@"C:\");
Console.WriteLine($"C: 可用空間: {FormatBytes(cDrive.AvailableFreeSpace)}");
using System;
using System.IO;
using System.Timers;
public class DiskSpaceMonitor : IDisposable
{
private readonly Timer _timer;
private readonly long _warningThresholdBytes;
private readonly Action _alertAction;
public DiskSpaceMonitor(string driveLetter, double warningThresholdGB, Action alertAction)
{
_warningThresholdBytes = (long)(warningThresholdGB * 1024 * 1024 * 1024);
_alertAction = alertAction;
_timer = new Timer(60000); // 每分鐘檢查一次
_timer.Elapsed += CheckDiskSpace;
_timer.AutoReset = true;
}
public void Start() => _timer.Start();
public void Stop() => _timer.Stop();
private void CheckDiskSpace(object sender, ElapsedEventArgs e)
{
try
{
DriveInfo drive = new DriveInfo(_timer.Tag?.ToString() ?? "C");
if (!drive.IsReady) return;
long freeSpace = drive.AvailableFreeSpace;
if (freeSpace < _warningThresholdBytes)
{
double freeGB = freeSpace / (1024.0 * 1024 * 1024);
_alertAction($"⚠️ 磁碟空間不足: {drive.Name} 剩餘 {freeGB:F2} GB (閾值: {_warningThresholdBytes / (1024.0*1024*1024):F1} GB)");
}
}
catch (Exception ex)
{
_alertAction($"磁碟監控錯誤: {ex.Message}");
}
}
public void Dispose()
{
_timer?.Stop();
_timer?.Dispose();
}
}
// 使用範例
var monitor = new DiskSpaceMonitor("C", 10, msg =>
{
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
// 可整合 Email、Slack、Windows 事件日誌等通知管道
});
monitor.Start();
// 程式結束時 monitor.Dispose();
public static long GetAvailableFreeSpace(string path)
{
// .NET Core 3.0+ / .NET 5+ 支援 Unix 掛載點
// Windows: DriveInfo 自動解析根目錄
// Linux: 需解析 /proc/mounts 或使用 statvfs (P/Invoke)
string root = Path.GetPathRoot(path);
if (string.IsNullOrEmpty(root))
root = Path.GetPathRoot(Path.GetFullPath(path));
var drive = new DriveInfo(root);
return drive.IsReady ? drive.AvailableFreeSpace : -1;
}
| 問題 | 原因 | 解決方案 |
|---|---|---|
| TotalSize 回傳負數 | 長度超過 Int32.MaxValue (2GB) | 屬性型別為 long,直接使用,勿轉 int |
| 光碟機 IsReady 為 false | 無媒體或媒體損壞 | 存取前必須檢查 IsReady,捕獲 IOException |
| 網路磁碟機查詢緩慢/逾時 | 網路延遲、離線 | 非同步執行、設定逾時、快取結果 |
| AvailableFreeSpace != TotalFreeSpace | 磁碟配額限制當前使用者 | 依據業務需求選擇:配額環境用 AvailableFreeSpace |
| VolumeLabel 存取拒絕 | 權限不足 | try-catch 包裹,或以管理員身分執行 |
| 單元測試難以模擬 | DriveInfo 為具體類別,無介面 | 建立包裝介面 IDriveInfoService 進行抽象 |
DriveType 多為 Fixed,Name 為掛載點路徑
// 跨平台安全列舉
public static IEnumerable GetValidDrives()
{
foreach (var drive in DriveInfo.GetDrives())
{
if (drive.IsReady)
yield return drive;
else
Console.WriteLine($"跳過未就緒磁碟: {drive.Name} ({drive.DriveType})");
}
}
public interface IDiskSpaceService
{
DriveInfoModel GetDriveInfo(string path);
IEnumerable GetAllDrives();
}
public record DriveInfoModel
{
public string Name { get; init; }
public DriveType Type { get; init; }
public string Format { get; init; }
public long TotalSize { get; init; }
public long FreeSpace { get; init; }
public string Label { get; init; }
public bool IsReady { get; init; }
}
public class DriveInfoService : IDiskSpaceService
{
public DriveInfoModel GetDriveInfo(string path)
{
var drive = new DriveInfo(Path.GetPathRoot(path));
return Map(drive);
}
public IEnumerable GetAllDrives()
{
return DriveInfo.GetDrives().Select(Map);
}
private DriveInfoModel Map(DriveInfo d) => new()
{
Name = d.Name,
Type = d.DriveType,
Format = d.DriveFormat,
TotalSize = d.TotalSize,
FreeSpace = d.AvailableFreeSpace,
Label = d.VolumeLabel,
IsReady = d.IsReady
};
}
// 測試時可注入 Mock
DriveInfo 是 .NET 存取磁碟資訊的標準 API,功能完整且跨平台支援良好。關鍵要點:
IsReadylong (64位),支援超大磁碟AvailableFreeSpace 反映實際可用空間 (含配額),TotalFreeSpace 為物理剩餘掌握這些核心概念,即可建立穩健的磁碟管理、監控與部署工具。