1

Is there a method that allows us to get its letter and physical type for each driver? That is, get one array where something like this will be:

$Drivers = *Get-Something*   # Where $Drivers is @{} array 
$Drivers
---
C: SSD
D: HDD
E: SSD
F: SSD

I need to bind the data of these two in an array. The first contains letters. the second contains physical types:

$DriversName = (Get-WmiObject -Class Win32_Volume).DriveLetter | Where-Object { $_ }
$DriversType = Get-PhysicalDisk | Select-Object -ExpandProperty MediaType

But I do not know which element of the first array refers to the element of the second array. Because the system does not prioritize them.

Thanks so much for the answers.

  • If I got you right there's already an answer [Combine Get-Disk info and LogicalDisk info in PowerShell?](https://stackoverflow.com/questions/31088930/combine-get-disk-info-and-logicaldisk-info-in-powershell) ... did you search for it before asking? – Olaf Jan 01 '20 at 17:47
  • Thanks. Yes, I saw this answer. However, he does not answer my question. I'm looking for. I need to associate a disk name with its type (SSD or HHD) – Кирилл Зацепин Jan 01 '20 at 17:52
  • You get the disks and the contained partitions, What do you need more? – Olaf Jan 01 '20 at 17:54
  • I need letters and physical type only. Namely, for example: 'C:' is 'SSD', 'D:' is 'HHD' – Кирилл Зацепин Jan 01 '20 at 18:01
  • This might work for you: https://www.pdq.com/blog/determining-disk-type-with-get-physicaldisk/ – Glenn Jan 01 '20 at 19:01

5 Answers5

3

This is working for me:

$partitions = Get-CimInstance Win32_DiskPartition
$physDisc = get-physicaldisk
$arr = @()
foreach ($partition in $partitions){
    $cims = Get-CimInstance -Query "ASSOCIATORS OF `
                          {Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} `
                          WHERE AssocClass=Win32_LogicalDiskToPartition"
    $regex = $partition.name -match "(\d+)"
    $physDiscNr = $matches[0]
    foreach ($cim in $cims){
        $arr += [PSCustomObject]@{
            Drive = $cim.deviceID
            Partition = $partition.name
            MediaType = $($physDisc | ? {$_.DeviceID -eq $physDiscNr} | select -expand MediaType)
        }
    }
}

$arr

It does seem kind of clunky though with the regex, so maybe there is a better approach I'm not seeing.

hcm
  • 922
  • 3
  • 10
  • Thanks so much for your work. However, not all MediaTypes are displayed. I have two disks. I could see MediaTypes for only one drive. That is, C: SSD, D: _ – Кирилл Зацепин Jan 02 '20 at 04:20
  • @КириллЗацепин As this is working on my stations, you will have to show where (and ideally why) this code is not working as expected. – hcm Jan 02 '20 at 07:17
  • @КириллЗацепин What kind of media types do you have in your pc. What output would you expect to see? – Olaf Jan 02 '20 at 07:24
  • Many thanks. I have C: SSD, D: SSD, E: HHD. I want to get the same output on the console. I am surprised that Powershell does not have such a method that would give both a letter and a media type. Therefore, my respect for you is that you find connections from different methods for matching. I'm not good Powershell yet, but I am taking a role model from you). No solution has yet been found, but one is nearby. – Кирилл Зацепин Jan 02 '20 at 11:39
3

First you want to look at Win32_LogicalDiskToPartition.

PS C:\> Get-WMIObject Win32_LogicalDiskToPartition | Select-Object Antecedent, Dependent | Write

Which gives on my system

Antecedent                                                                        Dependent
----------                                                                        ---------
\\DESKTOP-JJASNFC\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0" \\DESKTOP-JJASNFC\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
\\DESKTOP-JJASNFC\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #1" \\DESKTOP-JJASNFC\root\cimv2:Win32_LogicalDisk.DeviceID="D:"

Query Win32_LogicalDisk to get information about the drive letter.

Get-WMIObject Win32_LogicalDisk | Select DeviceID, Path | Write

yields for me

DeviceID Path
-------- ----
C:       \\DESKTOP-JJASNFC\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
D:       \\DESKTOP-JJASNFC\root\cimv2:Win32_LogicalDisk.DeviceID="D:"
F:       \\DESKTOP-JJASNFC\root\cimv2:Win32_LogicalDisk.DeviceID="F:"

Here the Path property is connected to the Dependent property we saw before.

In Win32_DiskPartition we can find the device Id

Get-WMIObject Win32_DiskPartition | Select DiskIndex, MedPath | Write

Again, for me

DiskIndex Path
--------- ----
        1 \\DESKTOP-JJASNFC\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0"
        0 \\DESKTOP-JJASNFC\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #0"
        0 \\DESKTOP-JJASNFC\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #1"

Now, the most interesting part for you is when we query MSFT_Physicaldisk.

Get-WmiObject MSFT_Physicaldisk -Namespace root\Microsoft\Windows\Storage | Select DeviceId, MediaType | Write

...

DeviceId MediaType
-------- ---------
1                4
0                4

Here, MediaType is the key. A value of 4 means SSD, 3 means HDD. DeviceId corresponds to the DiskIndex.

So, if you join those 4 "tables" together you can achieve what you want. My Powershell-Fu is not good enough.

To recap: The joins are like

MSFT_Physicaldisk.MediaType, MSFT_Physicaldisk.DeviceID <-->

Win32_DiskPartition.DiskIndex, *Win32_DiskPartition.Path <-->

Win32_LogicalDiskToPartition.Dependent, Win32_LogicalDiskToPartition.Antecedent <-->

Win32_LogicalDisk.Path, Win32_LogicalDisk.DeviceID

Holli
  • 5,072
  • 10
  • 27
  • I also suspect that `DiskIndex` is used as the `DeviceId` but could not find documentation around this - just observing that it _seems to be the case all the time_. Do you know if this is actually documented somewhere? – GaspardP Nov 21 '22 at 03:11
  • @Holli In `Win32_DiskPartition` above you probably mean `Path` instead of `MedPath` – wolfrevo May 13 '23 at 06:58
2

Here is the solution (thanks js2010 for the idea). Nearly. Since you need logical drives to display. Decision by Chris Dent:

powershell
Get-PhysicalDisk | ForEach-Object {
    $physicalDisk = $_
    $physicalDisk |
        Get-Disk |
        Get-Partition |
        Where-Object DriveLetter |
        Select-Object DriveLetter, @{n='MediaType';e={ $physicalDisk.MediaType }}
}
1

You can use the SerialNumber property of the disks to map the output and combine the logical drive letter with the MediaType of the physical disks.

# create a Hashtable to store the DriveLetter and SerialNumber obtained from WMI (I use Get-CimInstance here)
$ht = @{}
$wmiQuery1 = 'ASSOCIATORS OF {{Win32_DiskDrive.DeviceID="{0}"}} WHERE AssocClass = Win32_DiskDriveToDiskPartition'
$wmiQuery2 = 'ASSOCIATORS OF {{Win32_DiskPartition.DeviceID="{0}"}} WHERE AssocClass = Win32_LogicalDiskToPartition'

# for PowerShell < 3.0 use Get-WmiObject instead of Get-CimInstance
Get-CimInstance -ClassName Win32_DiskDrive | Where-Object { $_.MediaType -match '^(Fixed|External)' } |
    ForEach-Object {
        # store the disk serialnumber of the physical disk and get the get the partition info for each disk
        $serial = $_.SerialNumber                  
        Get-CimInstance -Query ($wmiQuery1 -f $_.DeviceID.Replace('\','\\'))   #'# double-up the backslashes
    } |
    ForEach-Object {
        # now get the logical disks on each partition to find the drive letters in property DeviceID
        Get-CimInstance -Query ($wmiQuery2 -f $_.DeviceID)
    } | 
    ForEach-Object { $ht[$_.DeviceID] = $serial }  # store the drive letters as key, the disk serial as value

# get the serialnumber and mediatype for each physical disk with Get-PhysicalDisk
$disks = Get-PhysicalDisk | Select-Object SerialNumber, MediaType

# loop through the Hashtable with partition/volume info gathered before and map on the SerialNumber property
$ht.Keys | ForEach-Object {
    $drive = $_
    $type = ($disks | Where-Object { $_.SerialNumber -eq $ht[$drive] }).MediaType
    [PsCustomObject]@{
        DriveLetter = $drive
        MediaType   = if ($type) { $type } else { 'Unspecified' }
    }        
} | Sort-Object DriveLetter

The result should look like

DriveLetter  MediaType
-----------  ---------
C:           SSD
D:           HHD
E:           SSD
F:           SSD
Theo
  • 57,719
  • 8
  • 24
  • 41
  • From my observations, these serials do not match. – hcm Jan 01 '20 at 20:05
  • @hcm I've changed the code to get the manufacturers serial number of the hard drive. My first attempt got the wrong serialnumber (the volume serial number given to it by windows) – Theo Jan 01 '20 at 20:31
  • That's working. Only downside: You are getting `MediaType` for the physical disks and not the partitions. So not all of your partitions are displayed. You'd have to turn it around to index the partitions instead of the physical drives. – hcm Jan 01 '20 at 21:32
  • @hcm Thanks for the input. Couldn't try it out, but will try your suggestion tomorrow on a Win10 machine. – Theo Jan 01 '20 at 21:50
  • Thanks so much for your work. However, not all MediaTypes are displayed. I have two disks. I could see MediaTypes for only one drive. That is, C: SSD, D: _. Perhaps because different methods display serial numbers differently. Perhaps the combination of disk names will help resolve the issue. – Кирилл Зацепин Jan 02 '20 at 04:54
  • @КириллЗацепин I have edited the code. This time around, the code should output values for all partitions/logical volumes on the disks. (thanks to [hcm](https://stackoverflow.com/users/12532197/hcm) who pointed this out) – Theo Jan 02 '20 at 08:54
  • Thank you very much for your elegant script. At the moment, the drive is still not displayed. Now along the road C: SSD and D: Unspecified (although it is SSD). Moreover, I connected one more HHD disk for verification and it is also Unspecified. – Кирилл Зацепин Jan 02 '20 at 11:27
  • I see at the methods "Get-CimInstance -ClassName Win32_DiskDrive" and "Get-PhysicalDisk" give different serial numbers for the same drives. For C: all right. For D: drive, one metot limits the serial number as 1234_5678_1234_5678, and the second as {12345dfs529fhd98394038dffle930dl3} – Кирилл Зацепин Jan 02 '20 at 11:27
  • I admire the way you operate Powershell. And I take an example from you too. No solution has yet been found, but one is nearby. – Кирилл Зацепин Jan 02 '20 at 11:42
0

Get-Volume returns DriveLetter and DriveType properties.

EDIT:

Get-PhysicalDisk has the MediaType property. But its ObjectId doesn't match up with a drive letter.

$disk = get-physicaldisk
$disk | get-disk | get-partition | select DriveLetter, 
  @{n='MediaType';e={$disk.MediaType}}

DriveLetter MediaType
----------- ---------
          C SSD

Hmm why doesn't pipevariable work? There can be multiple drive letters.

get-physicaldisk -pv disk | get-disk | get-partition | select DriveLetter,
  @{n='MediaType';e={$disk.MediaType}}

DriveLetter MediaType
----------- ---------
          C
js2010
  • 23,033
  • 6
  • 64
  • 66