I straightened out your code and ran it (I don't have SQL, though). I'm not sure what result you're trying to achieve, though. I get the "accurate results of CPU utilization" part, but not whether you're after only certain processes, or the total CPU for all processes, or something else. Right now the result are only the CPU consumption of the top "X" number processes regardless of what they are. Furthermore, it's only the top "X" results of each individual set of CounterSamples.
This is how I reformatted your code. I think it's more understandable. I hope you do, too:
Function Get-Cpu {
[CmdletBinding()]
Param (
[parameter(Mandatory, ValueFromPipeline)]
[String[]]$ServerInstance,
[parameter(Mandatory = $true)] $NumOfSessions
)
$template = [ordered]@{
SQLInstance = ""
TimeStamp = ""
Name = ""
CPU = ""
}
foreach ($i in $ServerInstance) {
Get-Counter -ComputerName $i -Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue | # gets all processes
Select-Object -ExpandProperty CounterSamples |
Where-Object { $_.Status -eq 0 } |
Sort-Object CookedValue -Descending |
Select-Object -First $NumOfSessions | # get only the top X number of CounterSamples
ForEach-Object{
$template.SQLInstance = $i
$template.TimeStamp = $_.TimeStamp
$template.Name = Try{
$procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
$proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId=$procId" -ErrorAction STOP
$procPath = ( $proc |
Where-Object { $_.ExecutablePath } |
Select-Object -First 1).ExecutablePath
$friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
$friendlyName
}
Catch{
$i # in case of failure use the server instance
}
$template.CPU = "{0:P}" -f (($_.CookedValue / 100 / $env:NUMBER_OF_PROCESSORS) / 100) # express result as percentage
[PSCustomObject]$template
}
}
}
Get-Cpu ws06 3
I left the "$friendlyName" variable in the code but it's not necessary. You can remove the "$friendlyName =" and keep the "[System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription". If you do, remove the "$friendlyName" right below that.