Reputation: 374
I'm writing a Hyper-V VM build script and wanted to add a feature to select a SSD where possible to prioritise smaller and most frequently used VMs. I first found the way in from the Scripting Guys here: http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/17/powertip-use-powershell-to-identify-ssd.aspx but I couldn't find anything that took me all of the way so I used WBEMTEST to find the classes I needed to query to make the connection between the SSD disk and the drive letter in question.
Click Start --> Run --> type WBEMTEST --> Check that the namespace is set to root\cimv2 and click Connect --> Enum Classes --> Recursive --> OK. About 5 seconds later the list will be fully populated allowing you to click on a list item. Click on a list item and then press the letter W to jump to Win32 and find one to look at then click Add. The properties and methods available are then shown.
The function IsSSDDrive below returns $True or $False depending on whether the given drive letter (including colon - e.g. C:) is mounted on a Solid State Disk (SSD) - assuming that the manufacturer inserted the letters SSD into the device name. This assumption ultimately makes this method unreliable so it would be wise to include some code to cross check using something like:
$DiskScore = (Get-WmiObject -Class Win32_WinSAT).DiskScore
If ($DiskScore -gt 6.9) { $SystemHasSSDDrive=$True } Else { $SystemHasSSDDrive=$False }
Write-Host "System Has SSD Drive: $SystemHasSSDDrive"
...if your environment uses such drives.
Function IsSSDDrive($Drive)
# Returns $True or $False depending on whether the given drive letter (including colon - e.g. C:) is mounted on a Solid State Disk (SSD) - assuming that the manufacturer inserted the letters SSD into the device name - which ultimately makes this method unreliable so beware to cross check using something like $DiskScore = (Get-WmiObject -Class Win32_WinSAT).DiskScore # Thanks to Rens Hollanders for this! http://renshollanders.nl/2013/01/sccm-mdt-identifying-ssds-from-your-task-sequence-by-windows-performance-index/
{
[array] $SSDDeviceIDList = $Null
[array] $SSDDeviceIDListF = $Null
[array] $DDListF = $Null
[array] $SSDDriveLetters = $Null
# Build a list of DeviceIDs of disk drives that contain the string SSD. Example output: \\.\PHYSICALDRIVE0, \\.\PHYSICALDRIVE1 etc
$SSDDeviceIDList = Get-WmiObject Win32_DiskDrive | where { $_.model -match 'SSD'} | Select 'DeviceID'
#$SSDDeviceIDList
# Fix the list by removing the \\.\ from each of the obtained \\.\PHYSICALDRIVEx values
ForEach ($SSDDeviceID in $SSDDeviceIDList) {
$SSDDeviceIDListF += $SSDDeviceID.DeviceID.ToString().Replace("\\.\","")
}
#$SSDDeviceIDListF
# Obtain disk drive to disk partition mapping information. Section of sample output for a single partition:
#Antecedent : \\MyComputerName\root\cimv2:Win32_DiskDrive.DeviceID="\\\\.\\PHYSICALDRIVE1"
#Dependent : \\MyComputerName\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #2"
$DDList1 = $null ; $DDList1 = Get-WmiObject Win32_DiskDriveToDiskPartition
# Look at each partition
ForEach ($Disk in $DDList1) {
# Iterate through the previously collected list of filtered (SSD in the name) hard drives
ForEach ($SSDDeviceID in $SSDDeviceIDListF) {
# If the partition is found with a property that matches the deviceID of the known-SSD list, then add the partition dependent information to the filtered (SSD) list of disk drives (DDListF)
If ($Disk.Antecedent.Contains($SSDDeviceID)) { $DDListF += $Disk.Dependent.Split([Char]34)[1] }
}
}
#$DDListF
# Obtain disk drive to disk partition mapping information. We need to do this because the drive letter attribute is not present in Win32_DiskDriveToDiskPartition and the physical disk is not present in Win32_LogicalDiskToPartition.
# Section of sample output for a single partition:
# Antecedent : \\MyComputerName\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #2"
# Dependent : \\MyComputerName\root\cimv2:Win32_LogicalDisk.DeviceID="I:"
$LDPList = Get-WmiObject Win32_LogicalDiskToPartition
# Look at each existing partition (on all drives)
ForEach ($Partition in $LDPList) {
# Iterate through the list of filtered SSD partitions
ForEach ($DDL in $DDListF) {
# If the disk-partition information from the SSD filtered list is found in the current partition then add the current partition's drive letter to the list of SSD drive letters
If ($Partition.Antecedent.Contains($DDL)) { $SSDDriveLetters += $Partition.Dependent.Split([Char]34)[1] }
}
}
$IsSSD = $False
If (!($SSDDriveLetters -eq $Null)) {
ForEach ($Item in $SSDDriveLetters) {
If ($Drive.ToUpper() -eq $Item.ToUpper()) {
$IsSSD = $True
break
}
}
}
Return $IsSSD
}
$d = IsSSDDrive "D:" # Returns True if the given drive letter resides on a disk with a name containing the letters SSD.
$d
$c = IsSSDDrive "C:"
$c
Upvotes: 2
Views: 4135
Reputation: 2423
Here is my rendition for checking whether current working directory is on an SSD:
function IsWorkingDirectorOnAnSSD {
$DriveLetter = $pwd.Path[0]
foreach ($Drive in Get-PhysicalDisk) {
if (($Drive | Get-Disk | Get-Partition).DriveLetter -Contains $DriveLetter) {
Return $Drive.MediaType -eq 'SSD'
}
}
}
This can be modified with drive letter as argument to check by drive letter.
Upvotes: 0
Reputation: 26
#return letters of disks and if SSD or HDD or Unspec..:
Get-PhysicalDisk | ForEach-Object {
$physicalDisk = $_
$physicalDisk | Get-Disk | Get-Partition |
Where-Object DriveLetter |Select-Object DriveLetter, @{n='MediaType';e={
$physicalDisk.MediaType }}
}
# | ft -HideTableHeaders if you don't want the table's headers.
Upvotes: 1
Reputation: 374
Here is a twist on the theme in case this is what you needed instead. This function returns an array of SSD drive letters - if any are found
Function GetSSDDriveLetters()
# Returns an array of SSD drive letters - if any are found - assuming that the manufacturer inserted the letters SSD into the device name - which ultimately makes this method unreliable so beware to cross check using something like $DiskScore = (Get-WmiObject -Class Win32_WinSAT).DiskScore # Thanks to Rens Hollanders for this! http://renshollanders.nl/2013/01/sccm-mdt-identifying-ssds-from-your-task-sequence-by-windows-performance-index/
# http://stackoverflow.com/questions/28731401/powershell-detect-if-drive-letter-is-mounted-on-a-ssd-solid-state-disk/28731402#28731402
{
[array] $SSDDeviceIDList = $Null
[array] $SSDDeviceIDListF = $Null
[array] $DDListF = $Null
[array] $SSDDriveLetters = $Null
# Build a list of DeviceIDs of disk drives that contain the string SSD. Example output: \\.\PHYSICALDRIVE0, \\.\PHYSICALDRIVE1 etc
$SSDDeviceIDList = Get-WmiObject Win32_DiskDrive | where { $_.model -match 'SSD'} | Select 'DeviceID'
#$SSDDeviceIDList
# Fix the list by removing the \\.\ from each of the obtained \\.\PHYSICALDRIVEx values
ForEach ($SSDDeviceID in $SSDDeviceIDList) {
$SSDDeviceIDListF += $SSDDeviceID.DeviceID.ToString().Replace("\\.\","")
}
#$SSDDeviceIDListF
# Obtain disk drive to disk partition mapping information. Section of sample output for a single partition:
#Antecedent : \\MyComputerName\root\cimv2:Win32_DiskDrive.DeviceID="\\\\.\\PHYSICALDRIVE1"
#Dependent : \\MyComputerName\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #2"
$DDList1 = $null ; $DDList1 = Get-WmiObject Win32_DiskDriveToDiskPartition
# Look at each partition
ForEach ($Disk in $DDList1) {
# Iterate through the previously collected list of filtered (SSD in the name) hard drives
ForEach ($SSDDeviceID in $SSDDeviceIDListF) {
# If the partition is found with a property that matches the deviceID of the known-SSD list, then add the partition dependent information to the filtered (SSD) list of disk drives (DDListF)
If ($Disk.Antecedent.Contains($SSDDeviceID)) { $DDListF += $Disk.Dependent.Split([Char]34)[1] }
}
}
#$DDListF
# Obtain disk drive to disk partition mapping information. We need to do this because the drive letter attribute is not present in Win32_DiskDriveToDiskPartition and the physical disk is not present in Win32_LogicalDiskToPartition.
# Section of sample output for a single partition:
# Antecedent : \\MyComputerName\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #2"
# Dependent : \\MyComputerName\root\cimv2:Win32_LogicalDisk.DeviceID="I:"
$LDPList = Get-WmiObject Win32_LogicalDiskToPartition
# Look at each existing partition (on all drives)
ForEach ($Partition in $LDPList) {
# Iterate through the list of filtered SSD partitions
ForEach ($DDL in $DDListF) {
# If the disk-partition information from the SSD filtered list is found in the current partition then add the current partition's drive letter to the list of SSD drive letters
If ($Partition.Antecedent.Contains($DDL)) { $SSDDriveLetters += $Partition.Dependent.Split([Char]34)[1] }
}
}
Return $SSDDriveLetters
}
GetSSDDriveLetters
Upvotes: 2