Process Monitoring with PowerShell

PowerShell MVP Jeff Hicks shares his script for watching processes using a WMI event subscription using the CIM cmdlets.

Source: Process Monitoring with PowerShell – Petri

$Poll = 120 #check the computer every two minutes

<#
I want to select all properties from the WMI class called CIM_InstModification.
This is a special system class that’s triggered when an object is modified.
I don’t want to find every object, as it is changed every second. So I tell WMI to check within a time frame of seconds.
When this event fires, WMI will have a new object called the TargetInstance.
This will be the changed object, and I only care about those that are Win32_Process objects.
The ISA operator accomplishes that.
The last part of the query is to limit results to those process objects, which is what the TargetInstance is, with a WorkingSetSize property of greater or equal to 500 MB.
#>

$query = “Select * from CIM_InstModification within $Poll where TargetInstance ISA ‘Win32_Process’ AND TargetInstance.WorkingSetSize>=$(1000MB)” #WMI query

<#
When you create the event subscriber, you can choose to simply record the events in your PowerShell session as matching events are detected.
Or you can take action.
In my case, I want to do a few things everytime a matching process is found.
I want to create a log file, and I want to display a popup message.
#>

$action={
#create a log file
$logPath= “C:\Work\HighMemLog.txt”
“[$(Get-Date)] Computername = $($Event.SourceEventArgs.NewEvent.SourceInstance.CSName)” | Out-File -FilePath $logPath -Append -Encoding ascii
“[$(Get-Date)] Process = $($Event.SourceEventArgs.NewEvent.SourceInstance.Name)” | Out-File -FilePath $logPath -Append -Encoding ascii
“[$(Get-Date)] Command = $($Event.SourceEventArgs.NewEvent.SourceInstance.Commandline)” | Out-File -FilePath $logPath -Append -Encoding ascii
“[$(Get-Date)] PID = $($Event.SourceEventArgs.NewEvent.SourceInstance.ProcessID)” | Out-File -FilePath $logPath -Append -Encoding ascii
“[$(Get-Date)] WS(MB) = $([math]::Round($Event.SourceEventArgs.NewEvent.SourceInstance.WorkingSetSize/1MB,2))” | Out-File -FilePath $logPath -Append -Encoding ascii
“[$(Get-Date)] $(‘*’ * 60)” | Out-File -FilePath $logPath -Append -Encoding ascii

#create a popup
$wsh = New-Object -ComObject Wscript.shell
$Title = “$(Get-Date) High Memory Alert”
$msg = @”
Process = $($Event.SourceEventArgs.NewEvent.SourceInstance.Name)
PID = $($Event.SourceEventArgs.NewEvent.SourceInstance.ProcessID)
WS(MB) = $([math]::Round($Event.SourceEventArgs.NewEvent.SourceInstance.WorkingSetSize/1MB,2))
“@

#timeout in seconds. Use -1 to require a user to click OK.
$Timeout = 10
$wsh.Popup($msg,$TimeOut,$Title,16+32)

}

#Now that I have the action scriptblock all that remains is to register the subscription with the Register-CimIndicationEvent.#
Register-CimIndicationEvent -Query $query -SourceIdentifier “HighProcessMemory” -Action $action

#You can see the registration with the Get-EventSubscriber cmdlet.
#This subscription will run for as long as my PowerShell session is running.
#The corollary is that I will need to recreate it every time I want to start monitoring.
#If this is a daily task, I could put it in my PowerShell profile script.

#If you want to get rid of the subscriber, simply unregister it.
#Get-EventSubscriber -SourceIdentifier “HighProcessMemory” | Unregister-Event