1

I'm trying to set up a script that generates blg files every set amount of time, using powershell. I know this can be done using perfmon XML templates, but for this specific project I have to do it with powershell if at all possible.

My main issue is that I am unable to store the list of performance counters I want to use in a variable and reuse them.

I've attempted to use the following script to create a list of performance counters to use:

$Counters = @()
$Counters += '\Memory\Available Bytes' 
$counters += '\Paging File(*)\% Usage'
$Counters += '\PhysicalDisk(*)\Disk Reads/sec'
$Counters += '\PhysicalDisk(*)\Disk Writes/sec'
$Counters += '\PhysicalDisk(*)\Avg. Disk sec/Read'
$Counters += '\PhysicalDisk(*)\Avg. Disk sec/Write'
$Counters += '\Processor(*)\% Processor Time'
$Counters += '\System\Processor Queue Length'
foreach($counter in $Counters)
{
$string = $string + ", '" + $counter + "'" 
$string = $string.TrimStart(",")
}

if I then proceed to use get-counter $string I get the following error:

Get-Counter : The specified counter path could not be interpreted.

Yet when I copy the exact value of the string, and use get-counter -counter Values of $string it works fine...

Could someone advise me on a way to get get-counter to work with either an array or a string with a list of counters?

Reaces
  • 5,547
  • 4
  • 36
  • 46

1 Answers1

2

When I use your += block, I get back a $counters that is a long concatenated string.

$counters += '\Memory\Available Bytes'
$counters += '\Paging File(*)\% Usage'
$counters += '\PhysicalDisk(*)\Disk Reads/sec'
$counters += '\PhysicalDisk(*)\Disk Writes/sec'
$counters += '\PhysicalDisk(*)\Avg. Disk sec/Read'
$counters += '\PhysicalDisk(*)\Avg. Disk sec/Write'
$counters += '\Processor(*)\% Processor Time'
$counters += '\System\Processor Queue Length'
$counters

\Memory\Available Bytes\Paging File(*)\% Usage\PhysicalDisk(*)\Disk Reads/sec\PhysicalDisk(*)\Disk Writes/sec\PhysicalDisk(*)\Avg. Disk sec/Read\PhysicalDisk(*)\Avg. Disk sec/Write\Processor(*)\% Processor Time\System\Processor Queue Length

$counters.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

That probably isn't what you want. If you make $counters an array explicitly things work a little better.

$counters = @()
$counters += '\Memory\Available Bytes' 
$counters += '\Paging File(*)\% Usage'
$counters += '\PhysicalDisk(*)\Disk Reads/sec'
$counters += '\PhysicalDisk(*)\Disk Writes/sec'
$counters += '\PhysicalDisk(*)\Avg. Disk sec/Read'
$counters += '\PhysicalDisk(*)\Avg. Disk sec/Write'
$counters += '\Processor(*)\% Processor Time'
$counters += '\System\Processor Queue Length'
$counters.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

$counters | Get-Counter
jscott
  • 24,204
  • 8
  • 77
  • 99
  • I'm afraid I was already using the same code, however when I use get-member it is still a string. However removing the trimming of the string seems to do the trick, so I was just doing too much it seems. – Reaces Sep 05 '14 at 07:11
  • 1
    `Get-Member` doesn't return "System.Array" because: [*"When you pipe a collection of objects to Get-Member, Get-Member gets the members of the individual objects in the collection, such as the properties of each string in an array of strings."*](http://technet.microsoft.com/en-us/library/hh849928.aspx) – jscott Sep 05 '14 at 09:48
  • Thank you, how then can I correctly verify if my variable is an array? – Reaces Sep 05 '14 at 10:02
  • Just as in the above: `$counters.GetType()` -- I edited the answer to show the differences between the two. – jscott Sep 05 '14 at 10:03