Module d'analyse : Afficher les premiers processus consommateurs de processeur

Microsoft.Windows.Server.TopCPUUsage.ProbeAction (ProbeActionModuleType)

Cette action d'analyse est utilisée par des tâches et des diagnostics d'analyse du processeur dans les packs d'administration de système d'exploitation spécifiques à une version.

Element properties:

TypeProbeActionModuleType
IsolationAny
AccessibilityPublic
RunAsDefault
InputTypeSystem.BaseData
OutputTypeSystem.CommandOutput

Member Modules:

ID Module Type TypeId RunAs 
TopCPUUsageProbe ProbeAction System.CommandExecuterProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalMillisecondsint$Config/IntervalMilliseconds$Intervalle (en millisecondes)
NumSamplesint$Config/NumSamples$Exemples de nombres

Source Code:

<ProbeActionModuleType ID="Microsoft.Windows.Server.TopCPUUsage.ProbeAction" Accessibility="Public">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalMilliseconds" type="xsd:int"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NumSamples" type="xsd:int"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalMilliseconds" ParameterType="int" Selector="$Config/IntervalMilliseconds$"/>
<OverrideableParameter ID="NumSamples" ParameterType="int" Selector="$Config/NumSamples$"/>
</OverrideableParameters>
<ModuleImplementation>
<Composite>
<MemberModules>
<ProbeAction ID="TopCPUUsageProbe" TypeID="System!System.CommandExecuterProbe">
<ApplicationName>%windir%\system32\windowspowershell\v1.0\powershell.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>-command "&amp; '$File/Microsoft.Windows.Server.TopCPUUsage.ps1$' $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$ $Config/IntervalMilliseconds$ $Config/NumSamples$"</CommandLine>
<TimeoutSeconds>300</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Microsoft.Windows.Server.TopCPUUsage.ps1</Name>
<Contents><Script>

param ([string] $TargetComputer, [Int] $SleepTime, [Int] $NumberOfSamples)

$ErrAction_None = 0
$ErrAction_Trace = 1
$ErrAction_ThrowError = 16
$ErrAction_Abort = 32
$ErrAction_ThrowErrorAndAbort = 48

$DISKSIZE_BYTES_IN_MB = 1048576

$g_ErrorEventNumber = 4001
$g_TraceEventNumber = 4002
$g_DebugFlag = $false

$WIN_SRV_2012_OSVer = "6.2"
#******************************************************************************
# FUNCTION: CheckByOSCurrentVersion
# DESCRIPTION: Returns True if the Registry Key for CurrentVersion
# is equal the target OS Versions Number.
# RETURNS: Boolean: True, if build is greater or equal than the given number
#******************************************************************************
function CheckByOSCurrentVersion()
{
$strCurrentOSVer = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
$strCurrentOSVer = $strCurrentOSVer.CurrentVersion
$CheckByOSCurrentVersion = $false
if($strCurrentOSVer -ge $WIN_SRV_2012_OSVer){
$CheckByOSCurrentVersion = $true
}else{
$CheckByOSCurrentVersion = $false
}
return $CheckByOSCurrentVersion;
}

$useCIM = CheckByOSCurrentVersion

#---------------------------------------------------------------------------
# Returns WMI Instance requested. Tries to execute WMI query a N times.
#---------------------------------------------------------------------------
Function WMIGetInstanceExTryN
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery,
[int]$N)

for ($i = 0; $i -lt $N; $i++)
{
$error.Clear();
if($useCIM){
$oInstance = Get-CimInstance -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
if ($error.Count -gt 0)
{
if ($i -eq ($N-1))
{
ThrowScriptError ("The class name '" + $sInstanceQuery + "' returned no instances. Please check to see if this is a valid WMI class name.") $error[0]
}
}
else
{
break;
}
sleep -m 1000
}

return $oInstance
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstanceEx
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)

$error.Clear();
if($useCIM){
$oInstance = Get-CimInstance -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
if ($error.Count -gt 0)
{
ThrowScriptError ("The class name '" + $sInstanceQuery + "' returned no instances. Please check to see if this is a valid WMI class name.") $error[0]
}

return $oInstance
}

#---------------------------------------------------------------------------
# Connect to WMI.
#---------------------------------------------------------------------------
Function WMIConnect
{
param ([string]$sTargetComputer,
[string]$sNamespace, $sInstanceQuery)

$error.Clear()

# !!! Refactoring comment:
# Original VBScript only tries to connect to the namespace. Piping to get only the first one saves time.
if($useCIM)
{
$oWMI = Get-CimClass -ComputerName $sTargetComputer -Namespace $sNamespace -ErrorAction SilentlyContinue | select -First 1
}else{
$oWMI = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue | select -First 1
}
if ($error.Count -gt 0)
{
$msg = "Unable to open WMI Namespace 'winmgmts:\\" + $sTargetComputer + "\" + $sNamespace + "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists."
ThrowScriptError $msg $error[0]
}
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstance
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)

WMIConnect $sTargetComputer $sNamespace $sInstanceQuery
$oInstance = WMIGetInstanceEx $sTargetComputer $sNamespace $sInstanceQuery
return $oInstance
}

#---------------------------------------------------------------------------
# Returns WMI Instance requested.
#---------------------------------------------------------------------------
Function WMIGetInstanceNoAbort
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sInstanceQuery)
if($useCIM){
$oInstance = Get-CimInstance -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}else{
$oInstance = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query ("Select * from "+$sInstanceQuery) -ErrorAction SilentlyContinue
}
return $oInstance
}

#---------------------------------------------------------------------------
# Executes the WMI query and returns the result set.
#---------------------------------------------------------------------------
Function WMIExecQuery
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sQuery)

$error.Clear()

if($useCIM){
$oQuery = Get-CimInstance -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}else{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}
if ($error.Count -gt 0)
{
ThrowScriptError ("The Query '" + $sQuery + "' returned an invalid result set. Please check to see if this is a valid WMI Query.") $error[0]
}

return $oQuery
}

#---------------------------------------------------------------------------
# Executes the WMI query and returns the result set, no abort version.
#---------------------------------------------------------------------------
Function WMIExecQueryNoAbort
{
param ([string]$sTargetComputer,
[string]$sNamespace,
[string]$sQuery)
if($useCIM){
$oQuery = Get-CimInstance -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}else{
$oQuery = Get-WMIObject -ComputerName $sTargetComputer -Namespace $sNamespace -Query $sQuery -ErrorAction SilentlyContinue
}

return $oQuery
}

#---------------------------------------------------------------------------
# Creates an event and sends it back to the mom server.
#---------------------------------------------------------------------------
Function ThrowScriptErrorNoAbort
{
param ([string]$sMessage,
[System.Management.Automation.ErrorRecord]$oErr)
# Retrieve the name of this (running) script
$ScriptFileName = $MyInvocation.ScriptName

if ($oErr -ne $null)
{
$sMessage = $sMessage + ". " + $oErr.ErrorDetails
}

$momAPI.LogScriptEvent($ScriptFileName, $g_ErrorEventNumber, $EVENT_TYPE_ERROR, $sMessage)

Write-Host $sMessage
}

#---------------------------------------------------------------------------
# Creates an event and sends it back to the mom server.
#---------------------------------------------------------------------------
Function ThrowScriptError
{
param ([string]$sMessage,
[System.Management.Automation.ErrorRecord]$oErr)
ThrowScriptErrorNoAbort $sMessage $oErr
exit
}

#---------------------------------------------------------------------------
# Outputs to file and echo for debugging purposes
#---------------------------------------------------------------------------
Function TraceLogMessage
{
param ([string]$sMessage)

Write-Host $sMessage

If ($g_DebugFlag -eq $true)
{
# Retrieve the name of this (running) script
$ScriptFileName = $MyInvocation.ScriptName

$momAPI.LogScriptEvent($ScriptFileName, $g_TraceEventNumber, $EVENT_TYPE_INFORMATION, $sMessage)
}
}

#---------------------------------------------------------------------------
# Verifies the expression. If equals to False then generates an error and quits the script
# Usage:
# Verify Not WMISet Is Nothing, "WMISet is invalid!"
# Verify WMISet.Count = 1, "Invalid quantity of services with name 'Server' (qty = " &amp; WMISet.Count &amp; ")."
#---------------------------------------------------------------------------
Function Verify
{
param ([bool]$bBool,
[string]$sMessage)

If ($bBool -eq $false)
{
ThrowScriptError $sMessage $null
}
}

Function GetRegistryKeyValue
{
param ([string]$keyPath,
[string]$key)

$error.Clear()

$strKeyValue = Get-ItemProperty -Path $keyPath -Name $key -ErrorAction SilentlyContinue
if ($error.Count -gt 0)
{
ThrowScriptError ("An error occurred while reading the registry: '" + $keyPath + $key + "'") $error[0]
}
return $strKeyValue.$key
}


#---------------------------------------------------------------------------
# Function: ExpressedInMB
# Usage:
# Parameter (SizeInBytes)
# Returns the Size Expressed in MBytes
#---------------------------------------------------------------------------
Function ExpressedInMB
{
param ($SizeInBytes)

$NumberSizeExpInMB = [math]::Round($SizeInBytes / $DISKSIZE_BYTES_IN_MB, 0)
return $NumberSizeExpInMB
}

#Copyright (c) Microsoft Corporation. All rights reserved.

# Parameters that should be passed to this script
# 0 Computer (FQDN)
# 1 SleepTime - interval (in milliseconds) between samples
# 2 NumberOfSamples

Function Main()
{
$lNumProcessors = GetNumProcessors $TargetComputer

# List processes using more than 1% of processor time (take into account the number of CPU).
# Sample &lt;NumberOfSamples&gt; times waiting &lt;SleepTime&gt; milliseconds between samples.

$processDictionary = @{}
for ($i = 1; $i -le $NumberOfSamples; $i++)
{
sleep -m $SleepTime

$PerfProc_Process = WMIGetInstanceEx $TargetComputer "root\cimv2" "Win32_PerfFormattedData_PerfProc_Process"

foreach ($process in $PerfProc_Process)
{
if ($process.Name -ne "_Total" -and $process.Name -ne "Idle") #-and $process.PercentProcessorTime -gt $lNumProcessors)
{
$key = $process.Name + "::" + $process.IDProcess
if ($processDictionary.ContainsKey($key))
{
$processDictionary[$key] = [double]$processDictionary[$key] + [double]$process.PercentProcessorTime
}
else
{
$processDictionary[$key] = [double]$process.PercentProcessorTime
}
}
}
}


# Collected Samples

# Get the keys
foreach ($key in $($processDictionary.Keys))
{
$processDictionary[$key] = [double]$processDictionary[$key] / [double]$NumberOfSamples / [double]$lNumProcessors
}

# Sort the array
$sortedProcessDictionary = $processDictionary.GetEnumerator() | Sort-Object -Property Value -Descending

Write-Host "% CPU Time(Avg) PID Binary Name "
Write-Host "==============================================================================="

for ($i = 0; $i -lt $sortedProcessDictionary.Count; $i++)
{
if ($sortedProcessDictionary[$i].Value -le 0)
{
break
}
$pValue = ([math]::Truncate($sortedProcessDictionary[$i].Value*10) / 10).ToString()
$pName = ($sortedProcessDictionary[$i].Key -split "::")[0]
$processid = ($sortedProcessDictionary[$i].Key -split "::")[1]
$OutPutString = " " + $pValue + "%"
for ($j = 0; $j -le (5-$pValue.Length); $j++) { $OutPutString += " " }
$OutPutString += " " + $processid
for ($j = 0; $j -le (8-$processid.Length); $j++) { $OutPutString += " " }
$OutPutString += " " + $pName
Write-Host $OutPutString
}
}

# Windows Server 2003, Windows XP, and Windows 2000: Because the NumberOfLogicalProcessors property
# is not available, NumberOfProcessors indicates the number of logical processors available in the
# system. In the case of a computer system that has two physical processors each containing two
# logical processors, the value of NumberOfProcessors is 4.
# For more information see "http://msdn2.microsoft.com/en-us/library/aa394102(VS.85).aspx"
Function GetNumProcessors{
param ([string]$sTargetComputer)

$WMISet = WMIGetInstanceEx $sTargetComputer "root\cimv2" "Win32_ComputerSystem"
foreach ($owObj in $WMISet)
{
$error.Clear()
$NumProcessors = $owObj.NumberOfLogicalProcessors
if ($error.Count -ne 0)
{
$NumProcessors = $owObj.NumberOfProcessors
}
return $NumProcessors
}
}

Main
</Script></Contents>
</File>
</Files>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="TopCPUUsageProbe"/>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.CommandOutput</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>