You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从USB驱动器名称获取磁盘索引?含分区/无分区及C#清理需求

解决C#中USB驱动器名称对应diskpart磁盘编号的问题

核心思路

要把DriveInfo获取的USB驱动器名称映射到diskpart的磁盘编号,需要通过WMI查询关联驱动器、分区、物理磁盘的层级关系——DriveInfo只能获取逻辑盘符,而diskpart操作的是物理磁盘,两者需要中间的分区信息做关联。同时要单独处理无分区的USB设备:这类设备没有逻辑盘符,DriveInfo无法枚举,得直接通过WMI筛选USB类型的物理磁盘。

实现步骤

1. 关联逻辑盘符到磁盘编号(带分区的USB)

通过Win32_LogicalDiskToPartition关联逻辑盘与分区,再通过Win32_DiskDriveToDiskPartition关联分区与物理磁盘,最终获取diskpart使用的磁盘编号(即物理磁盘的Index属性)。

示例代码:

using System.Management;

// 根据盘符获取对应的磁盘编号
public static int? GetDiskNumberFromDriveLetter(string driveLetter)
{
    // 统一盘符格式为X:
    if (!driveLetter.EndsWith(":"))
        driveLetter += ":";

    try
    {
        // 查询逻辑盘对应的分区
        var logicalDiskQuery = new ObjectQuery($"ASSOCIATORS OF {{Win32_LogicalDisk.DeviceID='{driveLetter}'}} WHERE AssocClass=Win32_LogicalDiskToPartition");
        using (var searcher = new ManagementObjectSearcher(logicalDiskQuery))
        {
            foreach (var partitionObj in searcher.Get())
            {
                // 查询分区对应的物理磁盘
                var diskQuery = new ObjectQuery($"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partitionObj["DeviceID"]}'}} WHERE AssocClass=Win32_DiskDriveToDiskPartition");
                using (var diskSearcher = new ManagementObjectSearcher(diskQuery))
                {
                    foreach (var diskObj in diskSearcher.Get())
                    {
                        return Convert.ToInt32(diskObj["Index"]);
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"查询磁盘编号失败: {ex.Message}");
    }
    return null;
}

2. 枚举无分区的USB物理磁盘

无分区USB没有逻辑盘符,需直接查询Win32_DiskDrive,筛选USB接口的磁盘且无关联分区的设备:

// 获取所有无分区的USB磁盘编号
public static List<int> GetUnpartitionedRemovableDisks()
{
    var diskNumbers = new List<int>();
    try
    {
        // 筛选USB接口的物理磁盘
        var query = new ObjectQuery("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
        using (var searcher = new ManagementObjectSearcher(query))
        {
            foreach (var diskObj in searcher.Get())
            {
                // 检查该磁盘是否有分区
                var partitionQuery = new ObjectQuery($"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{diskObj["DeviceID"]}'}} WHERE AssocClass=Win32_DiskDriveToDiskPartition");
                using (var partitionSearcher = new ManagementObjectSearcher(partitionQuery))
                {
                    if (partitionSearcher.Get().Count == 0)
                    {
                        diskNumbers.Add(Convert.ToInt32(diskObj["Index"]));
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"查询无分区磁盘失败: {ex.Message}");
    }
    return diskNumbers;
}

3. 整合逻辑并执行diskpart清理

将枚举USB、映射编号、执行清理命令的逻辑整合:

using System.Diagnostics;
using System.IO;

public static void CleanAllUsbDevices()
{
    // 处理带盘符的USB设备
    foreach (DriveInfo drive in DriveInfo.GetDrives())
    {
        if (drive.IsReady && drive.DriveType == DriveType.Removable)
        {
            var diskNumber = GetDiskNumberFromDriveLetter(drive.Name);
            if (diskNumber.HasValue)
            {
                ExecuteDiskpartClean(diskNumber.Value);
            }
        }
    }

    // 处理无分区的USB设备
    var unpartitionedDisks = GetUnpartitionedRemovableDisks();
    foreach (var diskNum in unpartitionedDisks)
    {
        ExecuteDiskpartClean(diskNum);
    }
}

// 执行diskpart清理命令
private static void ExecuteDiskpartClean(int diskNumber)
{
    // 构造diskpart脚本
    string scriptContent = $"select disk {diskNumber}\nclean\n";
    string tempScriptPath = Path.Combine(Path.GetTempPath(), "diskpart_clean_temp.txt");
    
    try
    {
        // 写入临时脚本文件
        File.WriteAllText(tempScriptPath, scriptContent);
        
        // 启动diskpart执行脚本
        var processStartInfo = new ProcessStartInfo
        {
            FileName = "diskpart.exe",
            Arguments = $"/s \"{tempScriptPath}\"",
            WindowStyle = ProcessWindowStyle.Hidden,
            CreateNoWindow = true,
            UseShellExecute = false
        };
        
        using (var proc = Process.Start(processStartInfo))
        {
            proc.WaitForExit();
            if (proc.ExitCode != 0)
            {
                Console.WriteLine($"清理磁盘{diskNumber}失败,退出码: {proc.ExitCode}");
            }
            else
            {
                Console.WriteLine($"磁盘{diskNumber}清理完成");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"执行diskpart失败: {ex.Message}");
    }
    finally
    {
        // 删除临时脚本
        if (File.Exists(tempScriptPath))
            File.Delete(tempScriptPath);
    }
}

关键注意事项

  • 权限要求:执行diskpart需要管理员权限,程序必须以管理员身份运行,否则会操作失败。
  • 数据风险:clean命令会彻底清除磁盘所有数据,务必在代码中增加校验逻辑,确保仅清理USB设备,避免误操作本地磁盘。
  • 设备兼容性:部分USB设备的MediaType属性可能不是"Removable Media",改用InterfaceType='USB'筛选更可靠。

(无分区USB示例图:USB without partition)

内容的提问来源于stack exchange,提问作者Milan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:50:30