Kae Travis

Use PowerShell to Monitor CPU and Memory Usage

Posted on by in PowerShell

This blog discusses how we can use PowerShell to monitor CPU and memory usage.

I was having a few issues recently on a web server whereby the server was becoming unresponsive due to either high CPU or memory usage.  It was difficult to debug since I could no longer remote desktop (RDP) onto it, or even VNC on to it.

When i restarted the server and checked the event logs, I couldn’t find anything of interest.  So I decided to knock up a quick PowerShell script to monitor for high CPU or memory usage.  If it detects this, it will dump all the current processes out to a local log file with their CPU/memory utilisation.  This way I could check the log file when I regained access, and check what was hogging all the resources.

I configured it to run every day using a scheduled task with the action of:

powershell.exe -ExecutionPolicy Bypass -File [PathToFile]

All you have to do is change $logFile to write to a log file of your choice, and $availablePercentageThreshold to a threshold value of your choice.  I’ve set it to 20, since I want to receive an alert (and process dump) if CPU or memory availability drops below 20% utilisation.

There is a section where you can add your own email notification code if required.  For this, you can read how to send emails using PowerShell.

cls
$logFile = "C:\Alkane\CPUMemory.log"

#if only this percentage of CPU/Memory OR LESS is available, dump process information to log and do something
$availablePercentageThreshold = 20

function Write-Log {
[CmdletBinding()]
param(
    [string]$message
)
    try {
        "$((Get-Date).tostring('dd/MM/yyyy HH:mm:ss')) - $message" | Out-File $logFile -Append
    } catch {}
}

#CPU availability
$cpuTime = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue

$availCPUPercentage = (100-$cpuTime)
$availCPUPercentageOutput = $availCPUPercentage.ToString("#,0.000") + "%"

#Mem availability
$totalRam = (Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).Sum
$availMem = (Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue

$availMemMB = $availMem.ToString('N0') + "MB"
$availMemPercentage = (104857600 * ($availMem/$totalRam))
$availMemPercentageOutput = $availMemPercentage.ToString('#,0.0') + "%"
   
Write-Log "Available CPU: $availCPUPercentageOutput" 
Write-Log "Available Memory: $availMemMB ($availMemPercentageOutput)"

if ($availCPUPercentage -lt $availablePercentageThreshold -or $availMemPercentage -lt $availablePercentageThreshold) {
 
    Write-Log "Dumping Processes..."

    get-process -IncludeUserName | Sort-Object -Property WorkingSet | foreach { 
        
        try {  
        Write-Log "************************************"
        Write-Log "ID: $($_.ID)"
        Write-Log "Process Name: $($_.processname)"
        Write-Log "Path: $($_.path)"
        Write-Log "UserName: $($_.username)"
        Write-Log "CPU: $($_.CPU)"
        Write-Log "Start Time: $($_.StartTime.tostring('dd/MM/yyyy HH:mm:ss'))"
        Write-Log "Handles: $($_.Handles)"
        Write-Log "Working Set Memory: $($_.WorkingSet)"
        Write-Log "PeakPaged Memory Size: $($_.PeakPagedMemorySize)"
        Write-Log "Private Memory Size: $($_.PrivateMemorySize)"
        Write-Log "Virtual Memory Size: $($_.VirtualMemorySize)"
        } catch {}
    }

    #Maybe send an email alert
}

Write-Log "Finished."


Use PowerShell to Monitor CPU and Memory Usage
Use PowerShell to Monitor CPU and Memory Usage

Leave a Reply