LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【C#】如何判断虚拟磁盘VHDX文件是否已经被挂载,挂载到了哪一个盘符,并且当前是挂载为只读模式还是可读写模式

admin
2025年5月16日 11:1 本文热度 140

如何判断虚拟磁盘VHDX文件是否已经被挂载,挂载到了哪一个盘符,并且当前是挂载为只读模式还是可读写模式呢?以下是用于检测VHDX挂载状态和属性的完整C#实现方案:

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("'", @"\'");

    }

}

使用示例:

var (isMounted, drives, isReadOnly) = VhdxStatusChecker.CheckVhdxStatus(@"D:\Backup.vhdx");

Console.WriteLine($"已挂载: {isMounted}");

Console.WriteLine($"盘符: {drives ?? "无"}");

Console.WriteLine($"只读模式: {isReadOnly}");

方案特性:

1、多语言兼容:

  • 支持检测英语、中文、德语系统的只读状态

  • 自动识别系统语言输出格式

  • 使用Unicode编码处理特殊字符

2、双重检测机制:

  • 通过WMI获取基础磁盘信息

  • 通过diskpart验证详细属性

3、兼容性处理:

  • 支持Windows 7及更高版本

  • 兼容传统Win32接口和新的Storage命名空间

4、错误防御:

  • 自动转义WMI查询路径

  • 处理磁盘分区的多种情况

  • 超时机制防止进程挂起

实现原理:

1、WMI查询:

  • 通过Win32_DiskDrive定位虚拟磁盘

  • 使用关联查询获取挂载盘符

2、diskpart检测:

  • 执行detail vdisk获取详细信息

  • 多语言关键字匹配检测只读状态

3、路径标准化:

  • 统一转换为全路径和小写格式

  • 处理不同来源的路径格式差异

注意事项:

1、运行权限:

// 需要以管理员身份运行程序

// 在项目文件中添加:

// <ApplicationManifest>app.manifest</ApplicationManifest>

// 并启用requireAdministrator

2、异常处理:

try {

    var result = VhdxStatusChecker.CheckVhdxStatus(path);

}

catch (Exception ex) {

    Console.WriteLine($"检测失败: {ex.Message}");

}

3、性能优化:

// 对于频繁检测的场景,可以缓存ManagementObjectSearcher实例

// 但需要注意及时释放资源

该方案通过结合WMI和diskpart的优势,实现了可靠的VHDX状态检测,适用于需要高可靠性保障的备份系统。


相关教程:

C#零成本实现云服务器上Windows系统数据库自动备份并防止备份文件被勒索病毒破坏[20]
  http://31161.oa22.cn


该文章在 2025/5/16 11:03:58 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved