Combine `Get-Disk` info and `LogicalDisk` info in PowerShell?
You need to query several WMI classes to get all information you want.
Win32_DiskDrive
gives you information about the physical disks.Win32_DiskPartition
gives you information about the partitions on the physical disks.Win32_LogicalDisk
gives you information about the filesystems inside the partitions.
Partitions can be mapped to their disks using the Win32_DiskDriveToDiskPartition
class, and drives can be mapped to their partitions via the Win32_LogicalDiskToPartition
class.
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 } } }}
How about like this...
Get-CimInstance Win32_Diskdrive -PipelineVariable disk |Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition -PipelineVariable partition |Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk |Select-Object @{n='Disk';e={$disk.deviceid}},@{n='DiskSize';e={$disk.size}},@{n='DiskModel';e={$disk.model}},@{n='Partition';e={$partition.name}},@{n='RawSize';e={$partition.size}},@{n='DriveLetter';e={$_.DeviceID}},VolumeName,Size,FreeSpace
Output:
Disk : \\.\PHYSICALDRIVE0DiskSize : 128034708480DiskModel : SAMSUNG MZ7PC128HAFU-000L5Partition : Disk #0, Partition #0RawSize : 128034595328DriveLetter : C:VolumeName : DISKSize : 128034594816FreeSpace : 7023042560
Inspired js2010's answer, with some enhancements:
For instance, the Manufacturer
field seems to have some a placeholder value when retrieved from the Win32_DiskDrive
instance, but has the proper value when using the Get-Disk
commandlet.
function Get-Drive { foreach($disk in Get-CimInstance Win32_Diskdrive) { $diskMetadata = Get-Disk | Where-Object { $_.Number -eq $disk.Index } | Select-Object -First 1 $partitions = Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition -InputObject $disk foreach($partition in $partitions) { $drives = Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk -InputObject $partition foreach($drive in $drives) { $totalSpace = [math]::Round($drive.Size / 1GB, 3) $freeSpace = [math]::Round($drive.FreeSpace / 1GB, 3) $usedSpace = [math]::Round($totalSpace - $freeSpace, 3) $volume = Get-Volume | Where-Object { $_.DriveLetter -eq $drive.DeviceID.Trim(":") } | Select-Object -First 1 [PSCustomObject] @{ DriveLetter = $drive.DeviceID Number = $disk.Index Label = $volume.FileSystemLabel Manufacturer = $diskMetadata.Manufacturer Model = $diskMetadata.Model SerialNumber = $diskMetadata.SerialNumber.Trim() Name = $disk.Caption FileSystem = $volume.FileSystem PartitionKind = $diskMetadata.PartitionStyle TotalSpace = $totalSpace FreeSpace = $freeSpace UsedSpace = $usedSpace Drive = $drive Partition = $partition Disk = $disk } } } }}
Example Usages:
Get-Drive | Format-ListGet-Drive | Where-Object { $_.DriveLetter -eq 'G:' }
Output:
DriveLetter : G:Number : 5Label : SE-LXY2-298GBManufacturer : SeagateModel : FreeAgent GoSerialNumber : 2GE45CK1Name : Seagate FreeAgent Go USB DeviceFileSystem : NTFSPartitionKind : MBRTotalSpace : 298.089FreeSpace : 297.865UsedSpace : 0.224Drive : Win32_LogicalDisk: G: (DeviceID = "G:")Partition : Win32_DiskPartition: Disk #5, Partition #0 (DeviceID = "Disk #5, Partition #0")Disk : Win32_DiskDrive: Seagate FreeAgent Go USB Device (DeviceID = "\\.\PHYSICALDRIVE5")