I was recently looking at obtaining volume information to include the volume name, capacity, free space, disk number and SCSI ID and to include information for both volumes that contained a drive letter or a folder path.
For instances running Windows 8 or Windows Server 2012 I was able to do this using a combination of retrieving WMI objects and using the Get-Partition cmdlet which is included in the storage module within these operating systems and then to export to a comma-separated values (CSV) file.
The requirement was to invoke the above agaisnt a collection of servers names, in this example I will be using a text file containing server names and loop through each one.
$Servers = Get-Content -Path "C:\Collection\Servers.txt" $Storage = ForEach ($Server in $Servers) {
I will then invoke, the Get-WMIObject cmdlet to query the Win32_Volume class to retrieve all local disks where the label is not equal to ‘System Reserved’.
$Volumes = Get-WmiObject Win32_Volume -ComputerName $Server | Where-Object {$_.DriveType -eq "3" -and $_.Label -ne "System Reserved"}
For each volume returned I will loop through each volume to retrieve the volume information and select the computer name, caption, capacity and free space, to include in the output:
ForEach ($Volume in $Volumes) { "" | Select-Object -Property @{N="Name";E={$Volume.PSComputerName}}, @{N="Caption";E={$Volume.Caption}}, @{N="Capacity (KB)";E={$Volume.Capacity}}, @{N="Free Space (KB)";E={$Volume.FreeSpace}},
As I am initially using the Win32_Volume to retrieve the volume information, I will not be able to return the disk number. In order to provide this information I used the Get-Partition cmdlet to compare the volume caption value returned and to filter the partitions retrieved by using the conditional operator function to return a match where the access path value was like the caption value.
@{N="Disk";E={Invoke-Command -ComputerName $Server -ScriptBlock {(Get-Partition | Where-Object {$_.AccessPaths -like $Using:Volume.Caption}).DiskNumber}}},
The final requirement is to include the SCSI ID by returning both the SCSI Port and TargetID of the volume. Again this information is not available from the Win32_volume class so as per the previous item, I will be able to return this information by retrieving the disk number using the Get-Partition cmdlet and then passing the disk number value returned to the Get-WMIObject to query the Win32_DiskDrive class and to return object where the Index value is equal to the disk number and then join both the SCSI Port and Target ID values.
@{N="SCSI Id";E={Invoke-Command -ComputerName $Server -ScriptBlock { $Disk = (Get-Partition | Where-Object {$_.AccessPaths -like $Using:Volume.Caption}).DiskNumber $SCSI = Get-WmiObject -Class Win32_DiskDrive | Where-Object {$_.Index -eq $Disk} "$($SCSI.SCSIPort):$($SCSI.SCSITargetID)"}}}
Finally, I will export the information for all servers in the collections to a comma-separated values (CSV) file.
{ { $Storage | Export-Csv -NoTypeInformation -UseCulture -Path "C:\Output\VolumeInformation.csv"