A question of the forums was asking about discovering disk information. They were trying to pipe the output of Get-WmiObject into another Get-WmiObject. that won’t work. There is another way. On Windows machines physical drives are divided into 1 or more partitions which are each divided into one or more logical disks. Linking disks, partitions and logical drives is a relatively simple process.
You can start at the physical disk and work down to the logical disks or start at the logical disk and work back to the physical disk. Lets start with the logical disk.
$diskinfo = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" | foreach { $props = $null $part = Get-CimAssociatedInstance -InputObject $psitem -ResultClass Win32_DiskPartition $disk = Get-CimAssociatedInstance -InputObject $part -ResultClassName Win32_DiskDrive $props = [ordered]@{ Disk = $disk.Index Model = $disk.Model Firmware = $disk.FirmwareRevision SerialNUmber = $disk.SerialNumber 'DiskSize(GB)' = [math]::Round(($disk.Size / 1GB ), 2) Partitions = $disk.Partitions Partition = $part.index BootPartition = $part.BootPartition 'PartitionSize(GB)' = [math]::Round(($part.Size / 1GB ), 2) Blocks = $part.NumberOfBlocks BlockSize = $part.BlockSize LDiskName = $psitem.Caption FileSystem = $psitem.FileSystem LDiskSize = [math]::Round(($psitem.Size / 1GB ), 2) LDiskFree = [math]::Round(($psitem.FreeSpace / 1GB ), 2) } New-Object -TypeName PSObject -Property $props } $diskinfo
Use Get-CimInstance to retrieve the instances of the Win32_LogicalDisk class. Use a filter for DriveType = 3 – which is local disks (as far as the server is concerned – they could be on a SAN or NAS).
Foreach of the disks get the associated partition and use that object to get the associated physical drive.
CIM (WMI) has the concept of associators and references.
A reference is a pointer showing you which instance is associated with another instance. For example:
PS> Get-CimInstance -ClassName Win32_LogicalDiskToPartition Antecedent : Win32_DiskPartition (DeviceID = "Disk #0, Partition #1") Dependent : Win32_LogicalDisk (DeviceID = "C:") EndingAddress : 511578663935 StartingAddress : 368050176 PSComputerName :
Logical disk C: is associated with partition #1 on disk #0
If you want to actually get the associated class then you do this
PS> $ld = Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DeviceID = "C:"' PS> Get-CimAssociatedInstance -InputObject $ld -ResultClass Win32_DiskPartition Name NumberOfBlocks BootPartition PrimaryPartition Size Index ---- -------------- ------------- ---------------- ---- ----- Disk #0, Part... 998458230 False True 511210613760 1
or
PS> Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DeviceID = "C:"' | Get-CimAssociatedInstance -ResultClass Win32_DiskPartition Name NumberOfBlocks BootPartition PrimaryPartition Size Index ---- -------------- ------------- ---------------- ---- ----- Disk #0, Part... 998458230 False True 511210613760 1
Once you’ve go the partition and physical disk instances. Populate your output object and loop. Notice that the pipeline is output directly to the variable $diskinfo. You don’t need to build arrays – get the pipeline to do it for you.
Each logical disk gets an output like this
Disk : 0 Model : Samsung SSD 840 PRO Series Firmware : DXM06B0Q SerialNUmber : S1AXNSAF329511V DiskSize(GB) : 476.93 Partitions : 3 Partition : 1 BootPartition : False PartitionSize(GB) : 476.1 Blocks : 998458230 BlockSize : 512 LDiskName : C: FileSystem : NTFS LDiskSize : 476.1 LDiskFree : 212.33
That’s working up the stack. What about working down. That’s a similar process:
$diskinfo = Get-CimInstance -ClassName Win32_DiskDrive | foreach { $disk = $psitem $parts = Get-CimAssociatedInstance -InputObject $psitem -ResultClass Win32_DiskPartition foreach ($part in $parts) { Get-CimAssociatedInstance -InputObject $part -ResultClassName Win32_LogicalDisk | foreach { $props = $null $props = [ordered]@{ Disk = $disk.Index Model = $disk.Model Firmware = $disk.FirmwareRevision SerialNUmber = $disk.SerialNumber 'DiskSize(GB)' = [math]::Round(($disk.Size / 1GB ), 2) Partitions = $disk.Partitions Partition = $part.index BootPartition = $part.BootPartition 'PartitionSize(GB)' = [math]::Round(($part.Size / 1GB ), 2) Blocks = $part.NumberOfBlocks BlockSize = $part.BlockSize LDiskName = $psitem.Caption FileSystem = $psitem.FileSystem LDiskSize = [math]::Round(($psitem.Size / 1GB ), 2) LDiskFree = [math]::Round(($psitem.FreeSpace / 1GB ), 2) } New-Object -TypeName PSObject -Property $props } } } $diskinfo
Start with getting the instances of Win32_Diskdrive. Foreach instance get the associated partitions – Win32_DiskPartition.
Iterate through the partitions and get the associated logical disk. Create your object and output.
NOTE: neither of these techniques will show the partitions that don’t contain logical drives so you won’t see the boot partition and other “hidden partitions” on modern Windows machines. if you need those look at Win32_DiskPartition directly.
The post Linking disks, partitions and logical drives appeared first on PowerShell for Windows Admins.