仅通过知道分区字母,在 C# 中使用 WMI 获取每个扇区的字节数

问题描述 投票:0回答:1

对于我的应用程序,我需要确定最佳的驱动器/分区。要求如下:

  1. 20GB或更多免费
  2. 驱动器必须是固定的(例如,它不能是可拆卸的 USB 驱动器等)
  3. 底层磁盘的 BytesPerSector 值必须为 512 或 4096。

第 1 点和第 2 点可以使用 C# 中的 DriveInfo 类轻松解析。然而我被困在第 3 点...

使用 ManagementObjectSearch 从 Win32_DiskDrive 类获取 BytesPerSector 值。但是我无法解析特定的驱动器。

例如。假设我想找到 C:\

的 BytesPerSector 值
            // Specify the drive letter (change it to the desired letter)
            string driveLetter = "C:";

            // Get DriveInfo for the specified drive letter
            DriveInfo driveInfo = new(driveLetter);

            // Check if the drive is ready (mounted)
            Assert.IsTrue(driveInfo.IsReady, $"Expected drive to be ready but was not");
            Console.WriteLine("Format: " + driveInfo.Name);
            // Get the disk drive associated with the partition
            var diskDrive = new System.Management.ManagementObjectSearcher(
                "SELECT * FROM Win32_DiskDrive WHERE DeviceID = '" + driveInfo.Name + "'"
            ).Get().OfType<System.Management.ManagementObject>().FirstOrDefault();

            // Check if the disk drive is found
            Assert.IsNotNull(diskDrive, $"Expected disk drive to be found but was null");

            // Get the BytesPerSector information
            uint bytesPerSector = Convert.ToUInt32(diskDrive["BytesPerSector"]);

            // Print out the BytesPerSector information
            Assert.IsTrue(bytesPerSector == 512 || bytesPerSector == 4096, $"Expected 512 or 4096 but was {bytesPerSector}");

此操作失败,但有例外:

留言: 测试方法 TestSectorInfo 抛出异常: System.Management.ManagementException:无效查询

一些挖掘让我发现 Win32_DiskDrive 期望的 DeviceID 看起来像这样:

 \\.\PHYSICALDRIVE0
 \\.\PHYSICALDRIVE1
等等

但是我无法确定 C:\ 是在 DRIVE0 还是 DRIVE1 上,所以我首先必须以某种方式将分区字母转换到其底层磁盘...我该怎么做?

我还尝试将卷的字母传递给不起作用的查询,并寻找任何可能做我需要的事情的c#类,但无济于事。

c# filesystems wmi enumeration
1个回答
0
投票

您遇到的问题是由于

Win32_DiskDrive
WMI 类的 DeviceID 与驱动器盘符不同所致。 DeviceID 是物理驱动器的唯一标识符,而不是分区或卷。

要获取特定驱动器号的

BytesPerSector
,您需要执行几个步骤:

获取盘符对应的Win32_Volume实例。 获取关联的

Win32_DiskPartition
实例。 获取关联的
Win32_DiskDrive
实例。 具体方法如下:

// Specify the drive letter (change it to the desired letter)
string driveLetter = "C:";

// Get the Win32_Volume instance for the drive letter
var volume = new System.Management.ManagementObjectSearcher(
    "SELECT * FROM Win32_Volume WHERE Name = '" + driveLetter + "\\'"
).Get().OfType<System.Management.ManagementObject>().FirstOrDefault();

// Check if the volume is found
Assert.IsNotNull(volume, $"Expected volume to be found but was null");

// Get the associated Win32_DiskPartition instance
var partition = new System.Management.ManagementObjectSearcher(
    "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + volume["DeviceID"] + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
).Get().OfType<System.Management.ManagementObject>().FirstOrDefault();

// Check if the partition is found
Assert.IsNotNull(partition, $"Expected partition to be found but was null");

// Get the associated Win32_DiskDrive instance
var diskDrive = new System.Management.ManagementObjectSearcher(
    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
).Get().OfType<System.Management.ManagementObject>().FirstOrDefault();

// Check if the disk drive is found
Assert.IsNotNull(diskDrive, $"Expected disk drive to be found but was null");

// Get the BytesPerSector information
uint bytesPerSector = Convert.ToUInt32(diskDrive["BytesPerSector"]);

// Print out the BytesPerSector information
Assert.IsTrue(bytesPerSector == 512 || bytesPerSector == 4096, $"Expected 512 or 4096 but was {bytesPerSector}");

此代码首先获取指定驱动器号的

Win32_Volume
实例。然后,它使用 ASSOCIATORS OF WQL 查询来获取关联的
Win32_DiskPartition
Win32_DiskDrive
实例。然后从
Win32_DiskDrive
实例检索 BytesPerSector 信息。

您可能需要以管理权限运行应用程序才能访问某些 WMI 类。另外,请记住将对

System.Management
命名空间和
System.Management
程序集的引用添加到您的项目中。

© www.soinside.com 2019 - 2024. All rights reserved.