Display Memory Usage with PowerShell

powershell-hero-img
Like most of you, I probably push my daily driver desktop too much. Usually I can tell when I’m running out of resources, simply by diminished responsiveness. With that said, it helps to quantify the sluggish responsiveness to better understand our memory needs. Most of my constraints are memory related, so I threw together a quick tool to show me how much memory is being used and how close to the edge I might be. There are several ways to get memory information, but I decided to use WMI and the Get-CimInstance cmdlet. You can get basic memory statistics from the Win32_OperatingSystem class.

$os = Get-Ciminstance Win32_OperatingSystem

As you can see, there are several memory-related properties.

Memory properties (Image Credit: Jeff Hicks)
Memory properties (Image Credit: Jeff Hicks)

Those values are all in bytes. I can use these values to calculate a percentage of free memory. I focused on physical memory.

$pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)

I’m using the Round() method from the .NET [Math] class to round the value to two decimal places. I can now display the relevant information using Select-Object and a few custom properties.

$os | Select @{Name = "PctFree"; Expression = {$pctFree}},
@{Name = "FreeGB";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalGB";Expression = {[int]($_.TotalVisibleMemorySize/1mb)}}

Displaying memory values (Image Credit: Jeff Hicks)
Displaying memory values (Image Credit: Jeff Hicks)

That’s a good start. Once I got that working, I extended my basic concept and came up with this function.

Function Test-MemoryUsage {
[cmdletbinding()]
Param()
$os = Get-Ciminstance Win32_OperatingSystem
$pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)
if ($pctFree -ge 45) {
$Status = "OK"
}
elseif ($pctFree -ge 15 ) {
$Status = "Warning"
}
else {
$Status = "Critical"
}
$os | Select @{Name = "Status";Expression = {$Status}},
@{Name = "PctFree"; Expression = {$pctFree}},
@{Name = "FreeGB";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalGB";Expression = {[int]($_.TotalVisibleMemorySize/1mb)}}
}

I used and If/ElseIf structure to evaluate the percentage of free memory and determine a status. Remember in an if statement, PowerShell stops checking after the first true evaluation, so I need to put my comparisons in ascending order.

Trying out the function (Image Credit: Jeff Hicks)
Trying out the function (Image Credit: Jeff Hicks)

I can even create an alias for it to save some typing.

Set-Alias -Name tmu -Value Test-MemoryUsage


But I want a bit more from this, perhaps something in color to highlight a critical condition. This should be simple enough. All I need to do is look at the status property and define an associated color.

$data = Test-MemoryUsage
Switch ($data.Status) {
 "OK" { $color = "Green" }
 "Warning" { $color = "Yellow" }
 "Critical" { $color = "Red" }
}

But let’s be real. I’m not going to type that every single time. Instead I built a second function, which has the sole purpose of displaying the data from Test-MemoryUsage into a report form that suits my needs complete with its own alias.

Function Show-MemoryUsage {
[cmdletbinding()]
Param()
#get memory usage data
$data = Test-MemoryUsage
Switch ($data.Status) {
"OK" { $color = "Green" }
"Warning" { $color = "Yellow" }
"Critical" {$color = "Red" }
}
$title = @"
Memory Check
------------
"@
Write-Host $title -foregroundColor Cyan
$data | Format-Table -AutoSize | Out-String | Write-Host -ForegroundColor $color
}
set-alias -Name smu -Value Show-MemoryUsage

Let me point out that normally you would not include any sort of formatting in a PowerShell function, nor would you use Write-Host to display results. But in this situation, that’s exactly what I want. The only purpose of this function is to show information on the screen.

Showing memory usage (Image Credit: Jeff Hicks)
Showing memory usage (Image Credit: Jeff Hicks)

I still have the first function if I need something in the pipeline. I put both functions and the Set-Alias commands in a PowerShell script and dot source it in my PowerShell profile.

. C:\Scripts\Check-MyMemory.ps1

You could also create a module. You could even extend these tools to query remote computers. You would want to include the computername in the output and maybe even a timestamp. Again, you could use the test function if you need to export the memory data to a CSV file or process it further in PowerShell. You can also use the show function to display information to the screen.

I realize it can be struggle to create a PowerShell tool that writes to the pipeline and is still user friendly. If you are running into that situation, perhaps you need to split your needs into multiple commands, as I’ve done in this example.