Remote Get-Counter


Today was a happy day. One of my co-workers asked me if I can help him with a little PowerShell.

I never say ‘no’ to this.


The Story

So, what’s the story? He needed to get some performance counters from a bunch of remote servers. Those are in different domain so Get-Counter won’t work – no Credential parameter. He wrapped it up in Invoke-Command, but then got some errors. Basically this was the ‘problematic’ part:

foreach ($server in $ServerList) {
#Generate all variables
$resultCounters = Invoke-Command ComputerName $server Credential $Credential ScriptBlock {
Get-Counter Counter $MetricList SampleInterval 10 MaxSamples 10
} ArgumentList $MetricList
$resultCounters | Export-Counter Path $path FileFormat $fileFormat

view raw


hosted with ❤ by GitHub

He wanted to generate counters on the endpoint, get the results through Invoke-Command and export them locally on his machine to further investigate. This is what he got:

The issue here is, that data returned through Invoke-Command is deserialized, which is not the original ‘object’:

So, I came up with a little bit different idea:

  1. Create several PowerShell Sessions to destination computers (based on xml input)
  2. Create an array of hashtables defining which counters are processed by which computer (different roles like SQL, IIS etc)
  3. Use Invoke-Command to:
    1. Generate destination file name based on computer name, date and other needed parameters
    2. Get Counters and export them on the machine directly
    3. Return object with computer name and destination file location
  4. Then, once the Invoke finishes, use foreach on processed computers to copy those files to his local machine using Copy-Item -FromSession (luckily, we’re working on Windows 10/2016 machines here)
  5. And finally clean up all PowerShellSessions created.

This is (nearly) the code we’ve end up:

$ComputerPSSession = New-PSSession ComputerName $ Credential $Credential
$params =@(
ComputerName = 'ComputerName1'
Counter = $MetricList
SampleInterval = 3
MaxSamples = 3
ComputerName = 'ComptuerName2'
Counter = $MetricList1
SampleInterval = 3
MaxSamples = 3
$processedComputers = invoke-command Session $ComputerPSSession ScriptBlock {
$fileName = '{0}_{1}_{2}.{3}' -f $USING:currentDate, $env:computername , $USING:profile, $USING:perfmonsOutputFileFormat
$destinationFileName = Join-Path Path $env:temp ChildPath $fileName
$currentParam = $USING:params | where-object {$PSItem.ComputerName -eq $env:computerName}
Get-Counter $currentParam | Export-Counter Path $destinationFileName FileFormat $USING:perfmonsOutputFileFormat
FilePath = $destinationFileName
ComputerName = $env:ComputerName
foreach ($Computer in $processedComputers) {
$currentSession = $ComputerPSSession | Where-Object {$PSItem.ComputerName -eq $Computer.PSComputerName}
Copy-Item FromSession $currentSession Path $Computer.FilePath Destination .\
if($ComputerPSSession) { $ComputerPSSession | Remove-PSSession }

view raw


hosted with ❤ by GitHub


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s