Remote Get-Counter

Fun!

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 {
param(
$MetricList
)
Get-Counter Counter $MetricList SampleInterval 10 MaxSamples 10
} ArgumentList $MetricList
$resultCounters | Export-Counter Path $path FileFormat $fileFormat
#
}

view raw

GetCounter.ps1

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 $ServerList.servers.server.name -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
[pscustomobject]@{
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

GetCounter1.ps1

hosted with ❤ by GitHub

Leave a comment