-2

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"))"

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
galileo
  • 59
  • 7
  • Perhaps storing your object path to a string before passing it into the `ManagementObject` would allow you to debug and ensure the path is correct. – Ibrennan208 Sep 19 '22 at 17:28
  • Also please provide the error context. Which line is throwing the error? – Ibrennan208 Sep 19 '22 at 17:28
  • Just a guess, perhaps the number does not need quotes surrounding it, where the ID would. – Ibrennan208 Sep 19 '22 at 17:29
  • 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"))" – galileo Sep 19 '22 at 17:32
  • Please add that to the question to provide the extra context. Comments could possibly get moved or edited and have no history visible to other potential answerers. – Ibrennan208 Sep 19 '22 at 17:35
  • @ lbrennan: OP updated and the removing the quotes: .Number=" + id); stills fails. – galileo Sep 19 '22 at 18:33
  • 1
    When constructing a `ManagementObject` for a specific instance the path must use a **key property**. In the [`MSFT_Disk` class](https://wutils.com/wmi/root/microsoft/windows/storage/msft_disk/) `Number` is not a key property, but `ObjectId` is, so try referring to it with that. `Win32_DiskDrive.DeviceID` works because that is a key property. – Lance U. Matthews Sep 21 '22 at 15:06
  • Understood. Can you point me to a list of or reference to the key properties? – galileo Sep 21 '22 at 21:59
  • See the link in my previous comment, or I see that `MSFT_Disk` is [documented on Microsoft.com](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-disk), although in this case you have to see the note that `MSFT_Disk` inherits from `MSFT_StorageObject` since Windows 10, and only that documentation lists `ObjectId` as a key property. You can use PowerShell to quickly list a class's key properties with `([WMIClass] 'root\Microsoft\Windows\Storage:MSFT_Disk').Properties | Where-Object { $_.Qualifiers.Name -contains 'key' }`. – Lance U. Matthews Sep 22 '22 at 00:45
  • The following may be of interest: [managementobject.cs](https://referencesource.microsoft.com/#System.Management/managementobject.cs) and [managementpath.cs](https://referencesource.microsoft.com/#System.Management/managementpath.cs). – Tu deschizi eu inchid Sep 22 '22 at 03:05
  • @ Lance: I missed the reference to the W10 note (or rather just didn't pay attention to it). The references to key properties in the MS docs are not presented as well - or as obviously - as they could be. – galileo Sep 24 '22 at 17:14

2 Answers2

1

@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;
        }
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
galileo
  • 59
  • 7
0

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:

Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24