A Script to Paste Performance Counters into PerfMon

A Script to Paste Performance Counters into PerfMon   

Overview

Click Here to download the Script and supporting files as a .zip file

If you have or know of other cool PerfMon tricks, I would very much appreciate it if you would send me a pointer.

If you've spent much time using PerfMon you may have experienced frustration with using the UI to add counters to monitor real-time. I know that I did. What I wanted was script that would take two parameters, a filename of a text file containing a list of computers and a filename of a text file containing a list of counters.

The list of computers would simply look something like the following:

Computer1

Computer2

The list of counters would simply look something list the following:

Processor(_Total)\% Processor Time

LogicalDisk(_Total)\% Disk Time

The Usage of the Script would be as follows:

PastePerfCounters.ps1 Filename_Computers.txt Filename_Counters.txt

Items to Understand First

Perfmon has a "Paste Counters" button

In the image below, please notice the button bar portion of the System Monitor Snap-In. Specifically, notice 5th and 6th buttons from the right. These are the "copy" and "paste counters" buttons. Many people that I talk to were not familiar with this capability of PerfMon so I'm pointing it out here. After you run the script described in this post, the clipboard will contain properly formatted text that can be pasted into PerfMon using the "paste counters" button. I'm looking for a way to automate this part too and have the counters just land in PerfMon but I haven't found a satisfying solution yet. If you have ideas, please email

PerfMon Main Window

Details

Perfmon Goo

In the script below, you will notice two template files are used. These two files, called BaseTemplate.txt and CounterTemplate.txt, must be located in the same directory as this script in order for everything to run as designed. These two files contain a lot of PerfMon Goo that I didn't want to put in the script. If you look at the contents of these two files, you will quickly realize that this is just a bunch of PerfMon settings. Yes, please feel free to change the template to suit your needs by modifying default values. However, if you break this file you will still copy information to the clipboard but it might not paste successfully into Perfmon or have the desired effects. To avoid problems, a good idea might be to make a backup copy of the original template files before you modify.

Non-Existent machines or counters

If you have bogus information in your lists or if the counters pasted are not functional on a machine in the computer list, then you will encounter errors. When you do, Perfmon will likely give you a dialog telling you what counters were bogus and then Perfmon will happily work with the rest.

The Script, in Powershell of course!

# Get the path to where the script lives

$ScriptBase = split-path -parent $myinvocation.mycommand.path

# In the same folder as this .ps1 file should exist the BaseTemplate.txt file

# This file contains much goo required by PerfMon to control various setttings

# You can modify this Template, but save the origional in case you make an invalid change

# Note if the BaseTemplate.txt file is not located, the script will exit with an error

$BaseTemplatePath = Join-Path $ScriptBase "\BaseTemplate.txt"

$BaseTemplateContent = Get-Content $BaseTemplatePath

Write-Output "Base path : $BaseTemplatePath"

# In the same folder as this .ps1 file should also exist the CounterTemplate.txt file

# This file contains much goo required by PerfMon to control various setttings

# You can modify this Template, but save the origional in case you make an invalid change

# Note if the CounterTemplate.txt file is not located, the script will exit with an error

$CounterTemplatePath = Join-Path $ScriptBase "\CounterTemplate.txt"

$CounterTemplateContent = Get-Content $CounterTemplatePath

Write-Output "Counter path : $CounterTemplatePath"

# Validate the the user passed in the correct number of args and

# call Write-Error to print a noticable usage statement if they did not

if ( $Args.Length -ne 2 ) {

    Write-Error "usage: Add-Counters <file containing list of counters> <file containing list of computers>"

    return

}

# If we get this far, we believe that we have two parameters which shoudl represent filenames

# for the ComputerList and the CountersList files

$ListOfComputersFile = $Args[0]

$ListOfCountersFile = $Args[1]

# Get the content from the computer and coutners files

$ComputerList = Get-Content $ListOfComputersFile

$CounterList = Get-Content $ListOfCountersFile

# Instantiate an ArrayList for us to work with

$CounterCollection = New-Object System.Collections.ArrayList

foreach ( $Computer in $ComputerList ) {

    foreach ( $Counter in $CounterList ) {

        if ( $Counter.IndexOf("\") -ne 0 ) {

            $data = "\\$Computer\$Counter"

        }else{

            $data = "\\$Computer$Counter"

        }

        Write-Output "Adding counter : $data"

        $CounterCollection.Add($data)

    }

}

$NumberOfCounters = $CounterCollection.Count

Write-Output "Number of counters : $NumberOfCounters"

$OutputBuffer = ""

$index = 1

$color = 0

foreach ( $item in $CounterCollection) {    

$indexString = "0000" + $index

    if ($indexString.Length -gt 5 ) { $indexString = "000" + $index }

    $OutputBuffer += [System.String]::Format($CounterTemplateContent, $item, $indexString, $color)    

    $index += 1

    $color += 10 }

#format the output

$BaseOutputBuffer = [System.String]::Format($BaseTemplateContent, $NumberOfCounters, $OutputBuffer)

$OutputFile = "temp_" + (Get-Date).ToString("ddMMyyyyhhmmss") + ".xml"

Add-Content $OutputFile $BaseOutputBuffer

#Copy to clip board

$BaseOutputBuffer | clip

Write-Output "Successfully added $NumberOfCounters counters to the clipboard"

Asks

If you find make any improvements to this script, please blog about them and post a comment on this posting pointing to your improvements.