0

I like to see every Partition/volume (also the hidden system volumes) on all physical disks. The Information of the Volume should contain

  • Partition Index (e.g. "1")
  • Name (e.g. "c:"),
  • Label (e.g. "Windows")
  • capacity (e.g. 200GB)

In my opinion "WMI" can be the right choice to solve this task.

The sample Output can look similar to this:

- PHYSICALDRIVE4
 -  --> 0 - m: - Data - 2TB
 - PHYSICALDRIVE1
 -  --> 0 - '' - System Reserved - 100MB
 -  --> 1 - c: - Windows - 100GB
 -  --> 2 - d: - Programs - 200GB
 - PHYSICALDRIVE2
 -  --> 0 - '' - Hidden Recovery Partition - 50GB
 -  --> 1 - f: - data - 1TB

I found several solutions in the web to get the driveletter (c:) combined with the diskid (disk0). One of those solution can be found here.

public Dictionary<string, string> GetDrives()
{
  var result = new Dictionary<string, string>();
  foreach ( var drive in new ManagementObjectSearcher( "Select * from Win32_LogicalDiskToPartition" ).Get().Cast<ManagementObject>().ToList() )
  {
    var driveLetter = Regex.Match( (string)drive[ "Dependent" ], @"DeviceID=""(.*)""" ).Groups[ 1 ].Value;
    var driveNumber = Regex.Match( (string)drive[ "Antecedent" ], @"Disk #(\d*)," ).Groups[ 1 ].Value;
    result.Add( driveLetter, driveNumber );
  }
  return result;
}

The Problem with this solution is that it ignores the hidden partitions. The output dictionary will only contain 4 entries (m,4 - c,1 - d,1 - f,2).

This is because of combining "win32_logicalDisk" with "win32_diskpartion" using "Win32_LogicalDiskToPartition". But "win32_logicalDisk" does not contain unassigned volumes.

I can find unassigned volumes only in "win32_volume" but I am not able to combine "win32_volume" with "win32_diskpartition".


Simplified my Dataclasses should look like this:

public class Disk
{
  public string Diskname; //"Disk0" or "0" or "PHYSICALDRIVE0"
  public List<Partition> PartitionList;
}

public class Partition
{
  public ushort Index //can be of type string too
  public string Letter; 
  public string Label; 
  public uint Capacity; 

  //Example for Windows Partition
  // Index  = "1" or "Partition1" 
  // Letter = "c" or "c:" 
  // Label = "Windows" 
  // Capacity = "1000202039296" 
  //
  //Example for System-reserved Partition
  // Index  = "0" or "Partition0"
  // Letter = "" or ""
  // Label = "System-reserved"
  // Capacity = "104853504"
}


Maybe anyone can help :-)

Community
  • 1
  • 1
mut
  • 11
  • 2

1 Answers1

0

MSFT_Partition in root\microsoft\windows\storage has all of the partitions, including the hidden ones. I grab the DiskNumber and Offset from that class, and then match them against the DiskIndex and StartingOffset value in Win32_DiskPartition. That combination should provide a unique identifier.

Start with Win32_DiskDrive, then get partitions using the method above. The MSFT_Partition object also has a property called AccessPaths, which will contain the DeviceID from Win32_Volume that you can check against to correlate volumes to partitions. Win32_LogicalDisk can then also be checked against the partition using the method you described, something like:

using (ManagementObjectSearcher LogicalDiskSearcher = new ManagementObjectSearcher(new ManagementScope(ManagementPath.DefaultPath), new ObjectQuery(String.Format("ASSOCIATORS OF {{Win32_DiskPartition.DeviceID=\"{0}\"}} WHERE AssocClass = Win32_LogicalDiskToPartition", ((string)Partition["DeviceID"]).Replace("\\", "\\\\")))))

This will get a collection of LogicalDisks from the partition, if any exist. Hope this kind of answers the question in case anyone else was having a similar issue. Unfortunately MSFT_Partition is only available on Windows 8/Server 2012 and later.

mhaken
  • 1,075
  • 4
  • 14
  • 28