0

I'm using the following command to get disk info:

get-ciminstance -ClassName Win32_LogicalDisk

The problem is, it doesn't contain the MediaType property (HDD, SSD, or in numerical form 4, 3 respectively).

I suppose I need to combine (associate) it with another command, like:

  • Get-PhysicalDisk or
  • Get-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage

I'm calling these commands from Node.js, so I can run separate commands and combine the results afterwards. It doesn't have to be 1 command. I'm just not sure how to correlate them, because Powershell API are inconsistent:

This one returns numbers

(Get-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage).DeviceID

And this one returns drive letters

(get-ciminstance -ClassName Win32_LogicalDisk).DeviceID

I found this code in another thread but I'm not sure how to add the MediaType property in it:

Get-WmiObject Win32_DiskDrive | ForEach-Object {
  $disk = $_
  $partitions = "ASSOCIATORS OF " +
                "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
                "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
  Get-WmiObject -Query $partitions | ForEach-Object {
    $partition = $_
    $drives = "ASSOCIATORS OF " +
              "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
              "WHERE AssocClass = Win32_LogicalDiskToPartition"
    Get-WmiObject -Query $drives | ForEach-Object {
      New-Object -Type PSCustomObject -Property @{
        Disk        = $disk.DeviceID
        DiskSize    = $disk.Size
        DiskModel   = $disk.Model
        Partition   = $partition.Name
        RawSize     = $partition.Size
        DriveLetter = $_.DeviceID
        VolumeName  = $_.VolumeName
        Size        = $_.Size
        FreeSpace   = $_.FreeSpace
      }
    }
  }
}
AlekseyHoffman
  • 2,438
  • 1
  • 8
  • 31
  • Are you sure, does this return MediaType? `Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object -Property MediaType` – jfrmilner Aug 22 '21 at 18:17
  • @jfrmilner yep, but that's a wrong MediaType, it returns some magical number 12, instead of 3 (SSD) or 4 (HDD). – AlekseyHoffman Aug 22 '21 at 19:12

2 Answers2

3

I've had mixed results with getting mediatype and other properties. Some systems return the actual values, others return the integer instead. Here is a snippet from a script of mine that may help you solve this.

Get-CimInstance Win32_Diskdrive -Filter "Partitions>0" | ForEach-Object {
    $disk = Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -Filter "SerialNumber='$($_.SerialNumber.trim())'"

    foreach($partition in $_ | Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition){
        foreach($logicaldisk in $partition | Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk){
            [PSCustomObject]@{
                Disk          = $_.DeviceID
                DiskModel     = $_.Model
                DiskSize      = $_.Size
                HealthStatus  = $disk.HealthStatus
                BusType       = $disk.BusType
                MediaType     = "{0} ({1})" -f $_.MediaType,$disk.MediaType
                Partition     = $partition.Name
                PartitionSize = $partition.Size
                VolumeName    = $logicaldisk.VolumeName
                DriveLetter   = $logicaldisk.DeviceID
                VolumeSize    = $logicaldisk.Size
                FreeSpace     = $logicaldisk.FreeSpace
            }
        }
    }
}

For those times when the code is returned instead, this can be ran instead.

$mediatypelist = @{
    '0' = 'Unspecified'
    '3' = 'HDD'
    '4' = 'SSD'
    '5' = 'SCM'
}

$healthstatuslist = @{
    '0' = 'Healthy'
    '1' = 'Warning'
    '2' = 'Unhealthy'
    '5' = 'Unknown'
}

$bustypelist = @{
    '0' = 'Unknown'
    '1' = 'SCSI'
    '2' = 'ATAPI'
    '3' = 'ATA'
    '4' = 'IEEE 1394'
    '5' = 'SSA'
    '6' = 'Fibre Channel'
    '7' = 'USB'
    '8' = 'RAID'
    '9' = 'iSCSI'
    '10' = 'Serial Attached SCSI (SAS)'
    '11' = 'Serial ATA (SATA)'
    '12' = 'Secure Digital (SD)'
    '13' = 'Multimedia Card (MMC)'
    '14' = 'This value is reserved for system use.'
    '15' = 'File-Backed Virtual'
    '16' = 'Storage Spaces'
    '17' = 'NVMe'
    '18' = 'This value is reserved for system use.'
}

Get-CimInstance Win32_Diskdrive -Filter "Partitions>0" | ForEach-Object {
    $disk = Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -Filter "SerialNumber='$($_.SerialNumber.trim())'"

    foreach($partition in $_ | Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition){
        foreach($logicaldisk in $partition | Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk){
            [PSCustomObject]@{
                Disk          = $_.DeviceID
                DiskModel     = $_.Model
                DiskSize      = $_.Size
                HealthStatus  = $healthstatuslist["$($disk.HealthStatus)"]
                BusType       = $bustypelist["$($disk.BusType)"]
                MediaType     = "{0} ({1})" -f $_.MediaType,$mediatypelist["$($disk.MediaType)"]
                Partition     = $partition.Name
                PartitionSize = $partition.Size
                VolumeName    = $logicaldisk.VolumeName
                DriveLetter   = $logicaldisk.DeviceID
                VolumeSize    = $logicaldisk.Size
                FreeSpace     = $logicaldisk.FreeSpace
            }
        }
    }
}
Doug Maurer
  • 8,090
  • 3
  • 12
  • 13
  • There's only 1 problem with it - I have a network drive `Z:` mapped to a folder on my HDD drive `E:`, however in the output of this snippet I get `DriveLetter : E:` for both the `E:` and `Z:` drives. If I run `get-ciminstance -ClassName Win32_LogicalDisk` separtely I see that the network drive has `Z:` letter assigned to it. Is there a way to fix this in this snippet? I think this issue is caused by the fact that `Get-CimInstance -ClassName MSFT_PhysicalDisk` doesn't return network drives – AlekseyHoffman Aug 22 '21 at 19:36
  • I don't get any of my mapped drives from `get-ciminstance -ClassName Win32_LogicalDisk`. The only thing used from `$disk` is `healthstatus`, `bustype`, and `mediatype`. The drive letter comes from the `$logicaldisk.deviceid` - need to figure out why that doesn't have the letter. – Doug Maurer Aug 22 '21 at 20:42
  • I think `MSFT_PhysicalDisk` cannot get Network drives in general, perhaps this snippet should get the whole list of drives from `Win32_LogicalDisk` and then populate the list the other way around from `MSFT_PhysicalDisk` into the output of `Win32_LogicalDisk`? – AlekseyHoffman Aug 22 '21 at 20:46
  • Like I said the physical disk is only used for three properties, none being the drive letter – Doug Maurer Aug 22 '21 at 21:19
  • It seems that `Get-CimAssociatedInstance` is getting the network source drive that it's mapped to. Maybe the code snippet should instead loop over `get-ciminstance -ClassName Win32_LogicalDisk` to get all the drives with correct drive letters and map the drives to the output of `Get-CimInstance Win32_Diskdrive`? This would also make it possible to get ProvideName property of the network drive – AlekseyHoffman Aug 22 '21 at 21:51
  • So you actually want the logical drives instead of physical? If you want to list them both together there will be a bunch of empty properties for network drives, a bunch. – Doug Maurer Aug 22 '21 at 22:45
  • Yeah, the list of all drives, including network ones. It seems that for the network drives the `Win32_LogicalDisk` class returns `size, drive letter, file system, ProviderName (network name), DriveType ("network" type)`,which is most of the properties you would need, at least for the locally mapped networks. – AlekseyHoffman Aug 22 '21 at 23:00
  • Could you please add another code snippet using the Win32_LogicalDisk to get the info for all available drives, including network ones? – AlekseyHoffman Aug 23 '21 at 14:08
1

I don't know if there is a more sophisticated way but I think it provides the result you expect.

$PhysicalDiskList = 
    Get-PhysicalDisk
$LogicalDiskList = 
    Get-CimInstance -ClassName CIM_LogicalDisk | 
        Where-Object -Property 'DriveType' -EQ -Value 3
$Result = 
foreach ($LogicalDisk in $LogicalDiskList) {
    $DiskPartition = 
        Get-CimAssociatedInstance -InputObject $LogicalDisk -ResultClass CIM_DiskPartition
    $PhysicalDisk = 
        $PhysicalDiskList | 
            Where-Object -Property 'DeviceID' -EQ -Value $DiskPartition.DiskIndex
    [PSCustomObject]@{
        DriveLetter = $LogicalDisk.DeviceID
        VolumeName  = $LogicalDisk.VolumeName
        Size        = $LogicalDisk.Size
        FreeSpace   = $LogicalDisk.FreeSpace
        DriveModel  = $PhysicalDisk.FriendlyName
        MediaType   = $PhysicalDisk.MediaType
    }
}

$Result | 
    Format-Table -AutoSize

It returns on my system the following:

DriveLetter VolumeName          Size    FreeSpace DriveModel                 MediaType
----------- ----------          ----    --------- ----------                 ---------
C:          System      254493077504  49397727232 SAMSUNG MZNTY256HDHP-000L7 SSD
D:          Data       1000067821568 643155914752 WDC WD10SPCX-08S8TT0       HDD
Olaf
  • 4,690
  • 2
  • 15
  • 23
  • Thanks for the answer. Unfortunately only the SSD drives have correct `MediaType: SSD`. The HDD drive has an empty `MediaType: ''`. Do you know why that's the case? When I run `Get-PhysicalDisk` separately I get correct results for all drives. – AlekseyHoffman Aug 22 '21 at 18:47
  • I don't know what to say. It works for me just as expected. – Olaf Aug 22 '21 at 18:52
  • My HDD has 2 partitions and a Network folder mapped on it, perhaps that's what causes the issue with HDD? If I delete everything after the `-Value $DiskPartition.DiskIndex` and just put `$PhysicalDisk` under it, it only returns the SSD drive. However the `$PhysicalDisk` a few lines above that returns all partitions from all drives – AlekseyHoffman Aug 22 '21 at 19:07
  • I changed the code to get only fixed disks - no DVD drives or Network drives. But more than one partition shouldn't be a problem. I tried that and it simply returns the same hardware information twice for both partitions on this disk. – Olaf Aug 22 '21 at 20:59
  • Thanks, unfortunately this solution wouldn't work for my use case. I do need the list of all drives, including network drives. Btw, for some reason the edited snippet still doesn't return `MediaType: 'HDD'` for the HDD drive – AlekseyHoffman Aug 22 '21 at 21:06
  • But there have to be empty values then because a network drive does not have an according hardware type available. So you have to change the code to output something like `n/a` for such cases then. – Olaf Aug 22 '21 at 21:09
  • I think I found the problem. The `$PhysicalDisk` variable in the line 7 of your **initial code** returns only the SSD, and the `$PhysicalDiskList` in line 8 returns the list of all partitions (repeating 5 times) with correct MediaType. So it seems the `[PSCustomObject]@` is getting the values from `$PhysicalDisk` instead of `$PhysicalDiskList`. Do you have any thoughts on how to fix this? – AlekseyHoffman Aug 22 '21 at 21:21
  • The code is syntactically correct. The variable `$PhysicalDisk` contains the according pyhsical disk object to the logical disk object treated in this loop iteration. – Olaf Aug 22 '21 at 21:28