Summary: Microsoft PowerShell MVP, Richard Siddaway, talks about using Windows PowerShell and WMI to work with performance counters and Windows assessment.

Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual PowerTip. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.

This excerpt is from PowerShell and WMI
  By Richard Siddaway 

Photo of book cover

Measuring system performance has traditionally involved looking at the performance counters. These can be accessed through the performance monitor (SYSMON for those who remember earlier versions of Windows), and they can be saved as required. You can also use the Get-Counter cmdlet (which works against remote machines), or you can use the WMI Win32_Perf* classes.

Windows Vista introduced the system assessment report. This rates a number of system hardware components (including memory, CPU, disk, and graphics) to produce an overall rating for the system. The higher the score, the better the system should perform.

I’m often asked about system stability. The number of unscheduled restarts is one way to measure stability. Later versions of Windows calculate a stability index on an hourly basis. This is calculated based on failures and changes, with recent events being more heavily weighted. The maximum possible score is 10.

Performance counters are still required to dig into individual aspects of the system. In this set of tips, we’ll cover performance counters and Windows system assessment reports.

Reading performance counters

If you’ve spent any time investigating system performance, you know that there’s a huge list of available Windows performance counters. The problem of finding the correct counter to use is increased when you consider that applications such as SQL Server, IIS, and Exchange Server add their own raft of counters. WMI enables you to access some, but not all, of the counters.

You can see which counters are available on a specific system like this: 

Get-WmiObject -List Win32_PerfFormattedData* | select name 

Here’s an extract from the results:

Win32_PerfFormattedData_PerfDisk_LogicalDisk

Win32_PerfFormattedData_PerfDisk_PhysicalDisk

Win32_PerfFormattedData_PerfOS_PagingFile

Win32_PerfFormattedData_PerfOS_Processor

Win32_PerfFormattedData_PerfOS_Memory

You should use the Recurse parameter when searching for these classes because they won’t necessarily be added to the default WMI namespace.

Tip   The Win32_PerfFormattedData class is a superclass that will call the other performance formatted data classes. There will be a lot of data to wade through.

There are also related classes that return the raw performance counter data. These classes are difficult to use, because each value has to be processed through a calculation to derive a meaningful result. It’s easier to use the formatted WMI classes or Get-Counter.

Problem

You need to monitor the processor performance of one of your systems. The server has multiple processors (or cores), and you need to display the information for each processor core and the total to ensure that the application is using the processor resources in an optimum manner.

Solution

The following listing presents a function that takes a computer name and a number as parameters. The number determines how many times you’ll sample the processor information.

Listing 1 Accessing performance counters

function get-cpucounter{

[CmdletBinding()]

param (

[parameter(ValueFromPipeline=$true,

   ValueFromPipelineByPropertyName=$true)]

   [string]$computername="$env:COMPUTERNAME",

   [int]$number=1

)

BEGIN{                                                              #1

$source=@"

public class CPUcounter

{

    public  string  Timestamp  {get; set;}

    public  string Name         {get; set;}

    public  ulong PercProcTime  {get; set;}

}

"@

Add-Type -TypeDefinition $source -Language CSharpversion3

}#begin

PROCESS{

1..$number | foreach {

 

$date = (Get-Date).ToString()

 

Get-WmiObject -Class Win32_PerfFormattedData_PerfOS_Processor `

 -ComputerName $computername | foreach {

    $value = New-Object -TypeName CPUCounter -Property @{

       TimeStamp = $date

       Name = $_.Name                                                 #2

       PercProcTime  = $_.PercentProcessorTime

    }

    $value

}

 

Start-Sleep -Seconds 1                                               #3

}

}#process

}

#1 Create class

#2 Create object and set properties

#3 Pause execution

Some inline C# code is used to create a new .NET class to store your results (#1). The class defines three properties—a timestamp, the name of the processor, and the percentage processor time (how much it was used during the measurement period). This is compiled by using Add-Type. Creating a class in this manner enables you to strongly type the properties, which supplies another level of error checking.

The range operator (..) is used to put the required series of numbers into the pipeline. Windows PowerShell will process each value, and for each of them retrieve the processor performance data by using Win32_PerfFormattedData_PerfOS_Processor. One object per processor, plus one for the total, will be returned. You create an object by using your specially created .NET class, populate its properties (#2), and output it. A one-second pause is activated before you start again (#3).

On my development system, I use this code: 

1..10 | foreach {Measure-Command -Expression {Get-WmiObject

 [CA] -Class Win32_PerfFormattedData_PerfOS_Processor  }} 

It show that the Get-WmiObject command takes about 300 milliseconds to retrieve the data. The function could be altered to change the delay, or you could even make it a parameter.

Discussion

The following image displays the results from using this function. The results show that processing is relatively equally distributed across the two cores. I wouldn’t expect to see the values being identical across all processors or cores all of the time.

Image of command output

Tip   In case you’re wondering how I managed to drive processor performance so high, I set a few continuously looping recursive directory listings. They’re a good way to tax the system without spending a lot of money on simulation tools.

Each of the WMI performance counter classes will need to be investigated to determine the properties that you need to record. For example, the class used here also returns information regarding interrupts.

One common scenario that you’ll get is users’ claiming a difference in performance between two systems. You can use the Windows system assessment report to provide a high-level comparison between the hardware of the two systems.

Windows system assessment report

The assessment report was introduced in Windows Vista. It examines a number of hardware components to determine an overall score for the system.

Tip   The overall score is determined by the lowest of the individual component scores. Always examine the full report to determine whether a single component is adversely affecting performance.

Accessing this information for the local computer through the GUI is acceptable, but you also need a way to perform this action remotely.

Problem

You need to create Windows system assessment reports for a number of remote computers. This will enable you to determine which computers should be refreshed and which are worth reusing.

Solution

The following listing utilizes the Win32_WinSat class to solve this issue. A hash table lookup is created to decode the assessment state property. 

Listing 2: System assessment information 

$satstate = DATA {

ConvertFrom-StringData -StringData @'

0 = StateUnknown

1 = Valid

2 = IncoherentWithHardware

3 = NoAssessmentAvailable

4 = Invalid

'@

}

 

function get-systemassessment{

[CmdletBinding()]

param (

[parameter(ValueFromPipeline=$true,

   ValueFromPipelineByPropertyName=$true )]

   [string]$computername="$env:COMPUTERNAME"

)

PROCESS{

 Get-WmiObject -Class Win32_WinSat -ComputerName $computername |

 select CPUScore, D3DScore, DiskScore, GraphicsScore,

 MemoryScore, TimeTaken,

 @{N="AssessmentState"; E={$satstate["$($_.WinSATAssessmentState)"]}},

 @{N="BaseScore"; E={$_.WinSPRLevel}}

 

}#process

}

 The function returns the data from the WMI class and uses Select-Object to output the properties and two calculated fields. One calculated field decodes the assessment state and the other renames the overall score.

Discussion

This report shouldn’t be taken in isolation when looking at system performance. The age of the system and any remaining warranty should also be considered.

Working with event logs, scheduled jobs, and performance indicators is an essential part of the administrator’s role. Windows PowerShell and WMI provide a number of tools to help you in these tasks:

  • Event log discovery and configuration
  • Backup and clearing of event logs
  • Lifecycle management for scheduled jobs, including creation, discovery, and deletion
  • Retrieval of data from performance counters
  • Production of system assessment reports and stability index data

These techniques enable you to gather data for possible forensic investigations, perform out-of-hours tasks through scheduling jobs, and determine how your systems are performing in real time and with a historic perspective. We discussed two of those techniques: performance counters and Windows system assessment reports.

~Richard

Here is the code for the discount offer today at www.manning.com: scriptw6
Valid for 50% off PowerShell and WMI and SharePoint 2010 Workflows in Action
Offer valid from April 6, 2013 12:01 AM until April 7, midnight (EST)

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy