C# WMI MSFT_Disk syntax

544 Views Asked by At

This form of ManagementObject (using ".DeviceID=") assignment works:

        // get number of logical drives on given physical disk
        int n = 0;
        var id = "\\\\.\\PHYSICALDRIVE0";
        var disk = new ManagementObject("Win32_DiskDrive.DeviceID=" + "'" + id + "'");
        foreach (ManagementObject dp in disk.GetRelated("Win32_DiskPartition"))
        {
            foreach (ManagementObject ld in dp.GetRelated("Win32_LogicalDisk")) ++n;
        }

This form of ManagementObject (using ".Number=") assignment fails:

        // get number of logical drives on given physical disk
        int n = 0;
        var id = "0";
        ManagementObject disk = new ManagementObject("root\\Microsoft\\Windows\\Storage:MSFT_Disk.Number=" + "'" + id + "'");
        foreach (ManagementObject dp in disk.GetRelated("MSFT_Partition"))
        {
            foreach (ManagementObject ld in dp.GetRelated("MSFT_Volume")) ++n;
        }

The exception is "Invalid object path". I have spent an embarrassing amount of time trying to figure out what I am doing wrong...and have no clue.

The specific item being searched for here is not the relevant issue. The proper syntax of using the two statements is what I am trying to understand...

The path for the working case is: "root\CIMV2" and the path to the failing case is: "root\Microsoft\Windows\Storage".

The failing statement is: "foreach (ManagementObject dp in disk.GetRelated("MSFT_Partition"))"

2

There are 2 best solutions below

1
user246821 On

There are a number of ways to retrieve the information. Try the following instead:

private int GetNumberOfLogicalDrives(int number)
{
    int numLogicalDrives = 0;
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(new ManagementScope(@"root\Microsoft\Windows\Storage"), new SelectQuery($"SELECT * FROM MSFT_Disk WHERE Number = {number}")))
    {
        using (ManagementObjectCollection logicalDrives = searcher.Get())
        {
            if (logicalDrives != null && logicalDrives.Count > 0)
            {
                foreach (ManagementObject mObj in logicalDrives)
                {
                    //re-initialize
                    numLogicalDrives = 0;

                    if (mObj == null)
                        continue;

                    foreach (ManagementObject mObjDP in mObj.GetRelated("MSFT_Partition"))
                    {
                        if (mObjDP == null)
                            continue;

                        foreach (ManagementObject mObjLD in mObjDP.GetRelated("MSFT_Volume"))
                        {
                            if (mObjLD == null)
                                continue;

                            //skip if there isn't a drive letter
                            if (String.IsNullOrEmpty(mObjLD["DriveLetter"]?.ToString().Trim()))
                                continue;

                            numLogicalDrives++; //increment
                        }
                    }

                    Debug.WriteLine($"number: {number}; numLogicalDrives: {numLogicalDrives}");
                }
            }
        }
    }

    return numLogicalDrives;
}

Usage:

int numLogicalDrives = GetNumberOfLogicalDrives(0);

Resources:

0
galileo On

@user9938: I appreciate your reply and the focus on the MSFT_xxx items. I was looking for an analogous syntax solution to the Win32_xxx approach.

After considerable trial and error, it appears that the approach of assigning the specific disk directly in the ManagementObject declaration statement is simply not supported when using MSFT_Disk.

Either of these two statements work correctly:

var disk = new ManagementObject("Win32_DiskDrive=
var disk = new ManagementObject("Win32_DiskDrive.DeviceID=

There does not appear to be any analogous statement when using MSFT_Disk.

Thus, the simplest code solution is:

        var phy = "0";    // ... or any valid disk index
        int num = 0;
        var disk = new ManagementObject("Win32_DiskDrive='\\\\.\\PHYSICALDRIVE" + phy + "'");
        foreach (ManagementObject dp in disk.GetRelated("Win32_DiskPartition"))
        {
            foreach (ManagementObject ld in dp.GetRelated("Win32_LogicalDisk")) ++num;
        }