Getting the Free Disk Space of Remote Computers
(For an updated version of this post and script, see Getting the Free Disk Space of Remote Computers Revisited.)
This started out as a simple script to try to get the free space on one of my servers, but I quickly discovered that using WMI’s Win32_LogicalDisk could only give me part of the solution. The catch is that Win32_LogicalDisk doesn’t return the information about volumes that aren’t assigned drive letters. Which is a problem if what you really need to know is how close to out of space your backup disk is! Because Windows Server Backup takes total control of the backup target disk, and doesn’t mount it as a drive letter, you need to use a different WMI Class to get the information you need. After asking some friends (PowerShell MVPs ROCK!), I was pointed to Win32_Volume, which returns all sorts of information about disk volumes whether they are assigned drive letters or not.
The next issue was how to get the actual information I wanted, and then to format it so that it actually made some sense. For example:
(Get-WmiObject –ComputerName Server1 –Class Win32_Volume).FreeSpace 21654667264 103541030912 75879378944 142417367040 5500928 565375053824 PSH>
This doesn’t really cut it. OK, let’s try at least getting it into a table:
Get-WmiObject –ComputerName Server1 –Class Win32_Volume | ft –auto DriveLetter,Label,FreeSpace DriveLetter Label FreeSpace ----------- ----- --------- C: 21655351296 D: DATA 103541030912 E: EXCHANGE 75879378944 F: FILES 142417367040 Y: New Volume 5500928 Server1 2014_10_15 10:57 DISK_03 565375053824
Well, that’s a bit more useful, but frankly, that number for the backup volume seems big, but is it 500 GB, or 50 GB? At first glance, I have no idea. And if it’s 50 GB, I’m in trouble, but if it’s 500 GB, we’re fine. So, we need to do a bit of manipulation to the output from Format-Table, and the tool for this is to create an Expression that allows you to calculate and format a result in a way that makes more sense. For this, we use an expression as the property to display. So, for example, to display that “565375053824” as Gigabytes, we use:
Get-WmiObject –ComputerName Server1 –Class Win32_Volume ` | ft –auto DriveLetter,` Label,` @{Label=”Free(GB)”;Expression={'{0:N0}’ –F ($_.FreeSpace/1GB)}}DriveLetter Label Free(GB) ----------- ----- -------- C: 20 D: DATA 96 E: EXCHANGE 71 F: FILES 133 Y: New Volume 0 Server1 2014_10_15 10:57 DISK_03 527
Now we’re getting somewhere. But what did we do? We use the @{} to tell Format-Table that we were going to use an expression to define a column of data. The Label=”Free(GB)” creates a new column header, and the Expression={“{0:N0}” –F means we’re going to have a numeric value (including thousands separators) with no decimal values. The calculated value for the column is ($_.FreeSpace/1GB).
So we now have a useful listing of free space on the remote server. Of course, it might be even more useful to know the percentage free. No problem, for that we use the formatting expression “{0:P0}” to express the column as a percentage, and use the calculation of ($_.FreeSpace/$_.Capacity), letting PowerShell do the work of converting that to a percentage. So:
Get-WmiObject –ComputerName Server1 –Class Win32_Volume ` | ft –auto DriveLetter,` Label,` @{Label=”Free(GB)”;Expression={“{0:N0}” –F ($_.FreeSpace/1GB)}},` @{Label=”%Free”;Expression={“{0:P0}” –F ($_.FreeSpace/$_.Capacity)}}DriveLetter Label Free(GB) %Free ----------- ----- -------- ----- C: 20 17 % D: DATA 96 48 % E: EXCHANGE 71 71 % F: FILES 133 18 % Y: New Volume 0 58 % Server1 12014_10_15 10:57 DISK_03 527 51 % <br>
Now we almost have it. Next, it would probably be useful to get the total capacity of the disk while we’re at it, and since I have more than one server, we should probably plan on passing this whole thing an array of computer names. So, the final script, at least for this first pass:
# ********************************************* # ScriptName: Get-myFreeSpace.ps1 # # Description: Script to get the free disk space # : on a remote computer and display it usefully # # ModHist: 26/11/2014 - Initial, Charlie # : 18/04/2017 - Change to Write-Output. # # # ********************************************* [CmdletBinding()] Param ([Parameter(Mandatory=$False,Position=0)] [String[]]$ComputerName = "Server1") Write-Output "" ForEach ( $Name in $ComputerName ) { Write-Output "Disk Utilization for server $Name is: " Get-WmiObject -ComputerName $Name -Class Win32_Volume ` | Format-Table -auto ` @{Label="Drive";` Expression={$_.DriveLetter};` Align="Right"},` @{Label="Free(GB)";` Expression={"{0:N0}" -f ($_.FreeSpace/1GB)};` Align="Right"},` @{Label="% Free";` Expression={"{0:P0}" -f ($_.FreeSpace / $_.Capacity)};` Align="Right"},` @{Label="Size(GB)";` Expression={"{0:N0}" -f ($_.Capacity / 1GB)};` Align="Right"},` @{Label="Volume Label";` Expression={$_.Label};` Width=25} }
You’ll see I tweaked the formatting to right align the calculated expressions, and gave my volume label column some extra space to improve readability. The result is:
Get-myFreeSpace.ps1 –ComputerName “Server1”,”Server2” Disk Utilization for server Server1 is: Drive Free(GB) % Free Size(GB) Volume Label ----- -------- ------ -------- ------------ C: 20 17 % 120 D: 96 48 % 200 DATA E: 71 71 % 100 EXCHANGE F: 133 18 % 750 FILES Y: 0 58 % 0 New Volume 527 51 % 1,024 Server1 2014_10_15 10:57 DISK_03 Disk Utilization for server Server2 is: Drive Free(GB) % Free Size(GB) Volume Label ----- -------- ------ -------- ------------ 0 25 % 0 D: 1,697 53 % 3,214 Data C: 484 95 % 512
ETA: Changed to use Write-Output instead of Write-Host. No need for the features of Write-Host, and it was causing issues for those who wanted to redirect the output to a file. This is more flexible.
ETA: Changed to clean up the problem formatting from the switch in syntax highlighters. Sigh.