Managing Perfmon Data Collector Sets with PowerShell

Whilst working with Microsoft Support on a performance case we needed to supply them with some Perfmon logs. To do so required creating a User Defined Data Collector Set containing a number of counters. You can obviously do this through the GUI, which is fine for one server, but we needed the logs from around 200 servers.

So we created a Data Collector Set on one server and then saved it out to a template which stores the data in an XML file. I then put together a script which read in the XML file and then used that data to create a Data Collector Set via the COM object Pla.DataCollectorSet. (There are currently no built-in Powershell cmdlets for doing this)

Since all of these servers were enabled for PowerShell remoting it was then very easy to execute that script on all 200 servers using Invoke-Command. I had issues reading in the XML file from a network location in my environment, so it first of all copies the file locally and removes it at the end. Note: it is important that you name the Data Collector Set the same as you did in the template, this allows for easier removal later on.

The resultant script is below. Most of the code around it is some basic error checking and using some of PowerShell 2.0’s built-in help and advanced function features. The key part that creates the Data Collector Set is here:


$datacollectorset = New-Object -COM Pla.DataCollectorSet
 $xml = Get-Content C:\temp\PerfmonTemplate.xml
 $datacollectorset.SetXml($xml)
 $datacollectorset.Commit("$DataCollectorName" , $null , 0x0003) | Out-Null
 $datacollectorset.start($false)

And the full script…….

<#
.SYNOPSIS
 Create a New Perfmon Data Collector Set from an XML input
.DESCRIPTION
 Create a New Perfmon Data Collector Set from an XML input
 Use PowerShell remoting to create these on a remote server.
 Remoting must be enabled on target servers
.NOTES
 Authors:  Jonathan Medd
.PARAMETER CSVFilePath
 Path of CSV file to import
.PARAMETER XMLFilePath
 Path of XML file to import
.PARAMETER DataCollectorName
 Name of new Data Collector. This should match the name in the XML file
.EXAMPLE
 New-DataCollectorSet -CSVFilePath C:\Scripts\Servers.csv -XMLFilePath C:\Scripts\PerfmonTemplate.xml -DataCollectorName CPUIssue
#>
param (
 [parameter(Mandatory=$True,HelpMessage='Path of CSV file to import')]
 $CSVFilePath
 ,
 [parameter(Mandatory=$True,HelpMessage='Path of XML file to import')]
 $XMLFilePath
 ,
 [parameter(Mandatory=$True,HelpMessage='Name of new Data Collector')]
 $DataCollectorName
 )

# Test for existence of supplied CSV and XML files
if (Test-Path $CSVFilePath){
 }
else{
 Write-Host "Path to CSV file is invalid, exiting script"
 Exit
 }
if (Test-Path $XMLFilePath){
 }
else{
 Write-Host "Path to XML file is invalid, exiting script"
 Exit
 }

# Generate list of servers to create Perfmon Data Collector Sets on
$servers = Get-Content $CSVFilePath

foreach ($server in $servers){

Write-Host "Creating Data Collector Set on $Server"

# Test if the folder C:\temp exists on the target server
if (Test-Path "\\$server\c$\Temp"){

 # Copy the XML file to the target server
 Copy-Item $XMLFilePath "\\$server\c$\Temp"

 # Use PowerShell Remoting to execute script block on target server
 Invoke-Command -ComputerName $server -ArgumentList $DataCollectorName -ScriptBlock {param($DataCollectorName)

 # Create a new DataCollectorSet COM object, read in the XML file,
 # use that to set the XML setting, create the DataCollectorSet,
 # start it.
 $datacollectorset = New-Object -COM Pla.DataCollectorSet
 $xml = Get-Content C:\temp\PerfmonTemplate.xml
 $datacollectorset.SetXml($xml)
 $datacollectorset.Commit("$DataCollectorName" , $null , 0x0003) | Out-Null
 $datacollectorset.start($false)
 }

 # Remove the XML file from the target server
 Remove-Item "\\$server\c$\Temp\PerfmonTemplate.xml"
 }
else{
 Write-Host "Target Server does not contain the folder C:\Temp"
 }
}

We calculated that this script would save 29 hours manual effort…….and that was just the first time we needed to do it. Later on we had to change some of the counters, so needed to first remove all of the Data Collector Sets and replace them with modified versions from a new XML file.

The following script removes an existing Data Collector Set and renames the folder it was storing logs in – this is because if you subsequently create a new one it will fail if you are using the same paths.


<#
.SYNOPSIS
 Remove a Specified Data Collector
.DESCRIPTION
 Remove a Specified Data Collector
.NOTES
 Authors:  Jonathan Medd
.PARAMETER CSVFilePath
 Path of CSV file to import
.PARAMETER DataCollectorName
 Name of existing Data Collector
.EXAMPLE
 Remove-DataCollectorSet -CSVFilePath C:\Scripts\Servers.csv -DataCollectorName CPUIssue
#>
param (
 [parameter(Mandatory=$True,HelpMessage='Path of CSV file to import')]
 $CSVFilePath
 ,
 [parameter(Mandatory=$True,HelpMessage='Name of existing Data Collector')]
 $DataCollectorName
 )

# Test for existence of supplied CSV file
if (Test-Path $CSVFilePath){
 }
else{
 Write-Host "Path to CSV file is invalid, exiting script"
 Exit
 }

# Generate list of servers to remove Perfmon Data Collector Sets from
$servers = Get-Content $CSVFilePath

# Create a string with the current date to append to the Perfmon folder name
$today = Get-Date
$RenameText = [string]$today.Day + [string]$today.Month + [string]$today.Year
$NewnameText = $DataCollectorName + '_' + $RenameText

foreach ($server in $servers){

Write-Host "Removing Collector Set for $Server"

# Use PowerShell Remoting to execute script block on target server
Invoke-Command -ComputerName $server -ArgumentList $DataCollectorName,$NewnameText,$Server -ScriptBlock {param($DataCollectorName, $NewnameText, $Server)

if (Test-Path C:\PerformanceLogs\$DataCollectorName) {

 $datacollectorset = New-Object -COM Pla.DataCollectorSet
 $datacollectorset.Query("$DataCollectorName",$null)
 $datacollectorset.stop($false)

 Start-Sleep 10

 $datacollectorset.Delete()

 Rename-Item -Path C:\PerformanceLogs\$DataCollectorName -NewName C:\PerformanceLogs\$NewnameText
 }
else {

 Write-Host "Collector Set for $Server Does Not Exist"

 }
}

}

13 thoughts on “Managing Perfmon Data Collector Sets with PowerShell

  1. While this is all cool, and actually great powershell code to study, is there are reason you didn’t just use logman.exe?

  2. Yep, exactly right. Could have used logman.exe, I guess I just think in PowerShell these days 🙂 As with any command line / scripting work, there’s usually more than one way to achieve the same thing!

  3. Thanks for putting this together. Do you know offhand if this will work with Windows 2003 based systems?

  4. The csv is just a list of computer names? If it’s really a csv then why do you use gc instead of import-csv?

  5. Heavily modified your scripts i know there may be easier ways of doing this now a days but i still prefer the old dot net com object methods because they are always viable.

    If you are interested in the updated versions i can send them to an Email address if you like.

  6. Thanks for the script. I am very new to Azure, powershell script etc. So, I really didnt follow what actually is being done in the above code.
    Currently, I am required to RDP to VM where my performance monitors are running and then start the performance counter sets manually by right clicking on each of the counter. But I would like all this to be automated using powershell script. So, is this achievable and how? Thanks in advance.

Comments are closed.