How to setup and start a Perfmon Counter via PowerShell v5 and above on Windows 10 Enterprise servers using xml template as Input

455 views Asked by At

I am troubleshooting some possible performance issues on Windows 10 Enterprise servers and want to setup performance counters for memory, and CPU Utilization for a few processes. I have setup few Perfmon counters and saved it as a xml template on one single server. My idea is to be able to use this template, push it across multiple servers, and then setup the same counters using this template so that i save manual effort of creating same counters across multiple servers. Is there any way to accomplish above tasks via PowerShell v5 and above? any other method to achieve the same via PowerShell?

I have saved my Perfmon counters as a xml template. I found that using - 'New-Object -COM Pla.DataCollectorSet' could be used to create a data collector set. unsure how to proceed further.

1

There are 1 answers

1
mlo3103 On

For a generic Data Colector set, I usually use 2 CSV files: 1 for computers list, and another for counters such as below:

counters list (CounterList.csv) file with header-

CntrPath
\LogicalDisk(C:)\Current Disk Queue Length
\LogicalDisk(C:)\Disk Bytes/sec
\LogicalDisk(C:)\Disk Read Bytes/sec
\LogicalDisk(C:)\Disk Write Bytes/sec
\LogicalDisk(C:)\Disk Writes/sec

Servers list (SrvList.csv) file with header-

Hostname
server1

Then I have a simple PS1 that combines the perf counters list with the machine names, and create a "test" Data Collector-

    # PerfLog.ps1
#   Variables
#------------

$ScriptPath       =   $MyInvocation.MyCommand.Path
$ScriptDir        =   Split-Path -Parent $ScriptPath
$CollectorSetName =   "Test"

# Files for input and output
$DataFilePath     = $ScriptDir
$SrvListFile      = $DataFilePath + "\SrvList.csv"
$CountersFile     = $DataFilePath + "\CounterList.csv"

# get Servers and the Performance Counters list
$Servers          = Import-Csv -Path $SrvListFile
$Counters         = Import-Csv -Path $CountersFile

$AllCountersList = @()


#   Main Program
#---------------
# create a new array for counters (with remote server names)
foreach ($Srv in $Servers)
  {  $SrvName = "\\" + $Srv.Hostname
    foreach ($counter in $Counters)
      { $newCounter       = $SrvName + $counter.CntrPath
        $AllCountersList += $newCounter
      }
  }

# Create a Data CollectorSet object
$datacollectorset = New-Object -COM Pla.DataCollectorSet
$datacollectorset.DisplayName = $CollectorSetName
$datacollectorset.Duration = 60                       # total logging duration in seconds
$datacollectorset.SubdirectoryFormat = 0              # alternate value = 1
$datacollectorset.SubdirectoryFormatPattern = $null   # alternate value = "yyyy\-MM"
$datacollectorset.RootPath = $ScriptDir + "\" + $CollectorSetName

# Create a Data Collector object and specify properties
$DataCollector = $datacollectorset.DataCollectors.CreateDataCollector(0)
$DataCollector.LogFileFormat = 0                      # formats are: 0- CSV, 1- TAB, 2- SQL, 3- BIN
$DataCollector.FileName = $CollectorSetName
$DataCollector.FileNameFormat = 0x1
$DataCollector.FileNameFormatPattern = "\-yyyy\-MM\-dd\_\_HH\-mm"
$DataCollector.SampleInterval = 30  # every 30 secs log data
$DataCollector.LogAppend = $false

# assign perf counters to the DataCollector
$DataCollector.PerformanceCounters = $AllCountersList

# specify credentials under which the collecto will operate
# if you're using a service account
# $datacollectorset.SetCredentials($global:U,$global:P)

    # DataCollector scheduling properties (if it is going to run on a schedule)
      #  $StartDate = [DateTime]('2022-07-01 07:00:00')
      #
      #  $NewSchedule = $datacollectorset.schedules.CreateSchedule()
      #  $NewSchedule.Days = 127
      #  $NewSchedule.StartDate = $StartDate
      #  $NewSchedule.StartTime = $StartDate

    # if a schedule is to be used, add the schedule!!! (disabled)
      #  $datacollectorset.schedules.Add($NewSchedule)
try
  {
    # Add the new DataCollector to the DataCollectorSet
    $datacollectorset.DataCollectors.Add($DataCollector)

    # commit the DataCollectorSet (should be visible in the Performance Mnitor mmc)
    $datacollectorset.Commit($CollectorSetName , $null , 0x0003) | Out-Null
    Write-Host "DataCollectorSet is comitted successfully for " + $CollectorSetName
  }
catch [Exception]
  { Write-Host "Exception Caught: " $_.Exception -ForegroundColor Red
  }

You can either use the commented out scheduling cmds (in the script) to configure scheduled run, or you can use below PS commands to manually start and stop the logger-

# Create a Data CollectorSet object
$CollectorSetName =   "Test"  # this should match the previously created DataColSet name
$dcs = New-Object -COM Pla.DataCollectorSet
# get ( query) DataCollectorSet
# which should return the configured DataCollectorSet object properties
$dcs.Query( $CollectorSetName, $null )

# then, to start the logging
$dcs.Start($false)

# or to stop the logging
$dcs.stop($false)
# to query if it is running (1) or stopped (0)
$dcs.status

You can extend this idea by using invoke-command with a loop (for each computer)to remotely deploy DCS and start,stop,and ask status.

see also: https://www.serverbrain.org/system-administration/how-to-use-powershell-to-manage-counter-logs.html https://www.jonathanmedd.net/2010/11/managing-perfmon-data-collector-sets-with-powershell.html