using System;
using System.IO;
using System.Management;
using System.Diagnostics;
using System.Text;
class VhdxStatusChecker
{
// 主檢查方法(返回:是否掛載,盤符列表,是否只讀)
public static (bool isMounted, string drives, bool isReadOnly) CheckVhdxStatus(string vhdxPath)
{
var normalizedPath = Path.GetFullPath(vhdxPath).ToLower();
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"))
{
foreach (ManagementObject disk in searcher.Get())
{
// 檢查磁盤是否為虛擬磁盤
if (disk["MediaType"]?.ToString() != "Microsoft Virtual Disk")
continue;
// 獲取VHDX文件路徑
var diskPath = GetVhdxPathFromDisk(disk);
if (diskPath == null) continue;
// 路徑匹配檢測
if (Path.GetFullPath(diskPath).ToLower() != normalizedPath)
continue;
// 獲取掛載信息
var drives = GetMountedDrives(disk);
var isReadOnly = CheckReadOnlyStatus(diskPath);
return (true, drives, isReadOnly);
}
}
return (false, null, false);
}
// 獲取VHDX文件路徑(兼容不同Windows版本)
private static string GetVhdxPathFromDisk(ManagementObject disk)
{
// 方法1:通過FileName屬性獲取
if (disk["FileName"] is string fileName && fileName.EndsWith(".vhdx", StringComparison.OrdinalIgnoreCase))
return fileName;
// 方法2:通過WMI擴展屬性獲取(需要Windows 8+)
try
{
using (var p = new ManagementObject($"Win32_DiskDrive.DeviceID='{disk["DeviceID"]}'"))
{
p.Scope = new ManagementScope(@"\\.\root\Microsoft\Windows\Storage");
return p["FileName"]?.ToString();
}
}
catch { /* 忽略兼容性錯誤 */ }
return null;
}
// 獲取已掛載的盤符
private static string GetMountedDrives(ManagementObject disk)
{
var sb = new StringBuilder();
var query = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{EscapeWmiPath(disk["DeviceID"].ToString())}'}} " +
"WHERE AssocClass = Win32_DiskDriveToDiskPartition";
using (var partitions = new ManagementObjectSearcher(query).Get())
{
foreach (ManagementObject partition in partitions)
{
var driveQuery = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{EscapeWmiPath(partition["DeviceID"].ToString())}'}} " +
"WHERE AssocClass = Win32_LogicalDiskToPartition";
using (var drives = new ManagementObjectSearcher(driveQuery).Get())
{
foreach (ManagementObject drive in drives)
{
if (drive["DeviceID"] != null)
sb.Append($"{drive["DeviceID"]} ");
}
}
}
}
return sb.ToString().Trim();
}
// 檢查只讀狀態(兼容多語言系統)
private static bool CheckReadOnlyStatus(string vhdxPath)
{
var output = ExecuteDiskPartCommand($@"
select vdisk file=""{vhdxPath}""
detail vdisk
exit
");
// 多語言匹配模式
var patterns = new[] {
new { Key = "Read-only", Yes = "Yes", No = "No" }, // 英語
new { Key = "只讀", Yes = "是", No = "否" }, // 中文
new { Key = "Schreibgeschützt", Yes = "Ja", No = "Nein" } // 德語
};
foreach (var pattern in patterns)
{
var start = output.IndexOf(pattern.Key);
if (start == -1) continue;
var valueStart = output.IndexOf(':', start) + 1;
var valueEnd = output.IndexOf('\n', valueStart);
var value = output.Substring(valueStart, valueEnd - valueStart).Trim();
return value.Equals(pattern.Yes, StringComparison.OrdinalIgnoreCase);
}
return false; // 默認返回可寫狀態
}
// 執行diskpart命令并獲取輸出
private static string ExecuteDiskPartCommand(string script)
{
var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, script, Encoding.Unicode); // 必須使用Unicode編碼
try
{
var psi = new ProcessStartInfo("diskpart")
{
Arguments = $"/s \"{tempFile}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.Unicode // 正確解析多語言輸出
};
using (var process = Process.Start(psi))
{
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit(5000);
return output;
}
}
finally
{
File.Delete(tempFile);
}
}
// WMI路徑轉義工具方法
private static string EscapeWmiPath(string path)
{
return path.Replace(@"\", @"\\").Replace("'", @"\'");
}
}