PotentEngineer

Intune, ConfigMgr, PowerShell and more...

4 minute read

Automating Performance Monitor in Windows

This post is the first of three for automating common debugging tools on Windows endpoints.

Earlier this year I came across a scenario of an application dropping connections. This was occuring across many hundreds of users and sporadically. Typically, I would attempt to recreate the issue so I could debug, but that was not possible here. I needed a way to be ready for the drop to occur and have all debugging tools setup proactively across a large number of users.

We use ConfigMgr to run scripts on workstations from a central location and it worked well in this scenario.

Initial setup process

  1. In Performance Monitor (perfmon.msc), create the necessary Data Collector Set, henceforth abbreviated DCS
    1. Be sure to specify the directory you want your output in
  2. Export the DCS you created. Right-click and Save template to .xml.
  3. Download Start-PerfmonCapture.ps1 linked below
  4. Copy the contents of the .xml into below script so no artifacts are necessary outside of the script. It is self-contained.
  5. Add a Run Script to ConfigMgr to be ran on devices, Start-PerfmonCapture
  6. Add the column for Script GUID to the ConfigMgr console and copy it out
  7. Create collection of target devices
  8. Trigger the Run script each morning at a specified time on target workstations to create and start the DCS using the Invoke-CMScript cmdlet. I used Azure Automation to trigger this daily and re-run hourly to ensure the DCS was always running. You can use any automation solution you prefer
    1. Invoke-CMScript -CollectionId <CollectionId> -ScriptGuid <scriptguid>

The script

This script is fairly basic, mostly just took figuring out how to interact with a Data Collector Set using logman.exe and make sure it didn’t clobber the existing DCS that is running.

Special thanks to Aussie Rob SQL, Jonathan Medd, and Rabi Achrafi for the example scripts I found online. References are in the script help text. Also thanks to my co-workers Darren Chinnon and Raul Colunga who helped put this together.

Script anatomy

  1. Populate the XML for the Data Collector Set
  2. Specify name of DCS
  3. Query if DCS already exists with specified name
  4. If DCS found, check if running
    1. If running, exit
    2. If not running, start it
  5. If DCS not found, create it and start it

Edit the lines below to personalize as needed

Partial Preview

$DCSName = 'PerfMonExample'
$DCSCheck = & logman query $DCSName # Query if DCS already exists

if ($DCSCheck[1] -like "*$($DCSName)") {
    Write-Output 'DCS found!'
	if ($DCSCheck[2] -like '*Running') {
		Write-Output 'Trace running, exiting...'
	} else {
		Write-Output 'Trace not running, starting...'
		& logman start $DCSName
	}
} else {
    Write-Output 'DCS not found, creating...'
    
    # Create the Data Collector Set
    $DCS = New-Object -COM Pla.DataCollectorSet
    $DCS.DisplayName = $DCSName
    $DCS.SetXml($DCSTemplate)
    $DCS.Commit("$DCSName" , $null , 0x0003)

    # Start the data collection
    Write-Output 'Starting the DCS!'
    $DCS.start($false)
}

Github Link: Start-PerfmonCapture.ps1

Output

The script gives a little output for validation, not much though. This is mostly for validation during testing.

Starting the script, there may be additional output from logman.exe for the initial run

Starting the script when DCS is already running

Starting the script when DCS is not running

Closing

Overall, this process worked well and met the need. It wasn’t the first time I had to use Perfmon and it won’t be the last. Up next, Wireshark.