# SCOM passes in the string "false" which won't bind to a [bool]
$Desc = [System.Convert]::ToBoolean($Descending);
# The cmdlet doesn't report % cpu usage, parent process id
$PoshProcesses = @(Get-Process)
# Get Proc usage statstics
# Wmi doesn't report process description and other fields
Function Get-WmiProcPerfSample
{
# Query Raw per process performance counters, excluding PID 0 as that will have Idle and _Total artificial processes listed.
Get-WmiObject -Class Win32_PerfRawData_PerfProc_Process -Filter 'IDProcess != 0' -Property IDProcess,CreatingProcessID,PercentProcessorTime,TimeStamp_Sys100NS,ElapsedTime
}
# Sample activity over 1 second (same as Task manager)
$WmiPerfData = @{}
$sampleSet1 = @{}
Get-WmiProcPerfSample | ForEach-Object {$sampleSet1[$_.IDProcess] = $_}
Start-Sleep -Seconds 1
# Take a second sample, and populate the WmiPerf hashtable with the results
Foreach ($sample in Get-WmiProcPerfSample) {
# If the process only appears in the second sample (started after the delay) you can use the lifetime values directly
$procTime = $sample.PercentProcessorTime
$timeWindow = ($sample.TimeStamp_Sys100NS - $sample.ElapsedTime)
# If the process existed in the first sample, use deltas over the sample period
If ($sampleSet1.ContainsKey($sample.IDProcess))
{
$procTime = $sample.PercentProcessorTime - $sampleSet1[$sample.IDProcess].PercentProcessorTime
$timeWindow = $sample.TimeStamp_Sys100NS - $sampleSet1[$sample.IDProcess].TimeStamp_Sys100NS
}
# Percent Processor Time will be accross all LogicalProcessors and can exceed 100
$WmiPerfData["$($sample.IDProcess)"] = New-Object -TypeName PSObject -Property @{
"PID"=$sample.IDProcess;
"CreatingProcessID"=$sample.CreatingProcessID;
"PercentProcessorTime"=($procTime / $timeWindow) * 100 / [System.Environment]::ProcessorCount
}
}
$OutputObjects= @();
foreach ($PoshProcess in $PoshProcesses)
{
$WmiProcess = $WmiPerfData["$($PoshProcess.Id)"];
if (-not $WmiProcess -or $PoshProcess.Id -eq 0) {
continue;
}
# Get properties of object to be displayed in output
# Get-Member can not be used here as it does not perserve the property order in the object
[System.Collections.ArrayList]$OutPutOrdering = $OutputObjects[0].psobject.Properties | Select-Object -ExpandProperty Name
# Add proprty being sorted, so it will be the first property to be displayed in output(will generate duplicate entry)
$OutPutOrdering.Insert(0,$OrderBy)
# Remove the duplicate from the list of properties (will preserve the first one in the list), and ensure they are strings to handle a PS v2 object wrapping issue with Select-Object
$OutPutOrdering = $OutPutOrdering | Select-Object -Unique | Foreach-Object {$_.ToString()}
# Done. (do not remove blank line following this comment as it can cause problems when script is sent to SCOM agent!) </Script></ScriptBody>
<Parameters>
<Parameter>
<Name>OrderBy</Name>
<Value>$Config/OrderBy$</Value>
</Parameter>
<Parameter>
<Name>Descending</Name>
<Value>$Config/Descending$</Value>
</Parameter>
<Parameter>
<Name>Top</Name>
<Value>$Config/Top$</Value>
</Parameter>
<Parameter>
<Name>Format</Name>
<Value>$Config/Format$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="WA"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>