Register for Semperis' Hybrid Identity Protection (HIP) Conference - June 30 - July 1 Register for Semperis' Hybrid Identity Protection (HIP) Conference - June 30 - July 1
PowerShell

Checking System Drive Free Space with WMI and PowerShell

Today’s article is another “ripped from the forums” inspired item. The question at hand is how to query the free space on the system drive for several remote computers. The system drive is normally C: as you can see with the %SystemDrive% environmental variable. But it doesn’t have to be, and in the original problem that was exactly the situation. Some servers might be C: but others might be D: or even E:, I suppose. So what’s the best way to use PowerShell to figure all of this out?

First off, let’s see what we need to get the free space information. We can use Get-Wmiobject and query the Win32_LogicalDisk class. We can also limit the query to the system drive. Since I already know in advance what that is I can run a command like this:

Get-WMIObject Win32_Logicaldisk -filter "deviceid='C:'" -ComputerName chi-core01
Getting disk information for the system drive (Image Credit: Jeff Hicks)
Getting disk information for the system drive (Image Credit: Jeff Hicks)

Of course, we can control what information to get.

Get-WMIObject Win32_Logicaldisk -filter "deviceid='C:'" -ComputerName chi-core01 |
Select PSComputername,DeviceID,Size,Freespace
Selecting key properties (Image Credit: Jeff Hicks)
Selecting key properties (Image Credit: Jeff Hicks)

The values are in bytes but they are easily converted using a custom hash table.

Get-WMIObject Win32_Logicaldisk -filter "deviceid='C:'" -ComputerName chi-core01 |
Select PSComputername,DeviceID,
@{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
@{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
Formatted results (Image Credit: Jeff Hicks)
Formatted results (Image Credit: Jeff Hicks)

I’m telling PowerShell to treat the size value as an integer and to round the free space value to two decimal points. Now that we know what we want to end up with, let’s take a step back and figure out how to determine what device ID to filter.

It turns out the Win32_OperatingSystem class has the information we need.

$OS = Get-WMiobject -Class Win32_operatingsystem -ComputerName chi-core01
$OS.SystemDrive
Finding the system drive from WMI (Image Credit: Jeff Hicks)
Finding the system drive from WMI (Image Credit: Jeff Hicks)

This means that if I didn’t know the system drive ahead of time, I could run my Win32_Logicaldisk query like this:

Get-WMIObject Win32_Logicaldisk -filter "deviceid='$($os.systemdrive)'" -ComputerName chi-core01 |
Select PSComputername,DeviceID,
@{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
@{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
Dynamically getting system drive size and freespace (Image Credit: Jeff Hicks)
Dynamically getting system drive size and freespace (Image Credit: Jeff Hicks)

And of course PowerShell easily scales.

$computers = "chi-core01","chi-hvr2","chi-fp02"
$computers | foreach {
 $os = Get-WmiObject win32_OperatingSystem -computername $_
 Get-WMIObject Win32_Logicaldisk -filter "deviceid='$($os.systemdrive)'" -ComputerName $_
} | Select PSComputername,DeviceID,
@{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
@{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}} |
Sort FreeGB | Format-Table -Autosize

Sorted and formatted results (Image Credit: Jeff Hicks)
Sorted and formatted results (Image Credit: Jeff Hicks)

In this example I had to run a separate WMI command to get the SystemDrive from Win32_OperatingSystem. I have to query each computer separately so that I can correlate the system drive for each one. But if I wanted to be clever, I could use a nested command.

$computers | foreach {
Get-WMIObject Win32_Logicaldisk -filter "deviceid='$((Get-WMIObject Win32_OperatingSystem -computername $_).systemdrive)'" -ComputerName $_
} |
Select PSComputername,DeviceID,
@{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
@{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}} |
Sort FreeGB | Format-Table -AutoSize

This will give me the same result. This is definitely a bit more convoluted and requires the use of sub-expressions and nested commands. Although one benefit of processing computers individually is that it makes it easier to handle errors. I made it easy by using computers that I knew were running in my $computers variable. But most likely that isn’t always going to be true.
$computers | foreach {
#define a named variable for the computername so that it can be used the Catch
#scriptblock
$computer = $_
Try {
  $os = Get-WmiObject win32_OperatingSystem -computername $computer -ErrorAction Stop
  #continue if there were no errors
  Get-WMIObject Win32_Logicaldisk -filter "deviceid='$($os.systemdrive)'" -ComputerName $computer
}
Catch {
  #$_ is the error object
  Write-Warning "Failed to get OperatingSystem information from $computer. $($_.Exception.Message)"
}
} | Select PSComputername,DeviceID,
@{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
@{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}} |
Sort FreeGB | Format-Table –AutoSize

Added error handling with Try/Catch (Image Credit: Jeff Hicks)
Added error handling with Try/Catch (Image Credit: Jeff Hicks)

I’ve given you a lot of PowerShell code to digest, so I think we’ll wrap it up for today. But we’ll be back to this topic and scenario because it offers a good platform for learning more about PowerShell.

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (0)

Leave a Reply

Register for the Hybrid Identity Protection (HIP) Europe Conference!

Hybrid Identity Protection (HIP) Europe 2021 - Virtual Conference

Mobile workforces, cloud applications, and digitalization are changing every aspect of the modern enterprise. And with radical transformation come new business risks. Hybrid Identity Protection (HIP) is the premier educational forum for identity-centric practitioners. At the inaugural HIP Europe, join your local IAM experts and Microsoft MVPs to learn all the latest from the Hybrid Identity world.