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"))"
CodePudding user response:
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:
CodePudding user response:
@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 & 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;
}