Your strategic advantage starts here

Use Powershell to Monitor CPU and Memory Usage

Use Powershell to Monitor CPU and Memory Usage

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."
Related Posts
Leave a Reply
Give us a call

Available from 9am to 8pm, Monday to Friday.

Send us a message

Send your message any time you want.

Our usual reply time: 1 Business day
Give us a call

Available from 9am to 8pm, Monday to Friday.

Send us a message

Send your message any time you want.

Our usual reply time: 1 Business day