I am trying to graph a Performance Monitor counter from our Hyper-V hosts that has multiple objects and I am getting the following error in PRTG:

XML: XML Parser mismatch: Wanted </>, got </prtg> -- JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231)

I am using the following PowerShell script:

Invoke-Command -ComputerName computer -ScriptBlock {Get-Counter "\Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch" |
  
  ForEach-Object CounterSamples |
  Where-Object InstanceName -ne _total |
  ForEach-Object {
    $InstanceName = $_.InstanceName
    $Value        = $_.CookedValue
 Write-Host
       "<prtg>"
       "<result>"
       "<channel>$InstanceName</channel>"
       "<value>$Value</value>"
       "</result>"
       "</prtg>"

  }
  }
Write-Host "</prtg>"

When I rung the script in PowerShell I get the following output to screen

<prtg>
<result>
<channel>computer1:hv vp 1</channel>
<value>7740.49019607843</value>
</result>
</prtg>

<prtg>
<result>
<channel>computer1:hv vp 0</channel>
<value>10382.5023227005</value>
</result>
</prtg>

<prtg>
<result>
<channel>computer2:hv vp 3</channel>
<value>1897.42268041237</value>
</result>
</prtg>

<prtg>
<result>
<channel>computer2:hv vp 2</channel>
<value>17919.1033138402</value>
</result>
</prtg>

Article Comments

There's a slight mistake in your output:

Write-Host "<prtg>"
Invoke-Command -ComputerName computer -ScriptBlock {Get-Counter "\Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per Dispatch" |
  
  ForEach-Object CounterSamples |
  Where-Object InstanceName -ne _total |
  ForEach-Object {
    $InstanceName = $_.InstanceName
    $Value        = $_.CookedValue
 Write-Host
       "<result>"
       "<channel>$InstanceName</channel>"
       "<value>$Value</value>"
       "</result>"
  }
  }
Write-Host "</prtg>"

The <prtg> and </prtg> tags ony mark the start and end of the actual output. It may as well be that PRTG doesn't see the console output, as you're using Invoke-Command on another host. The Get-Counter cmdlet also has a ComputerName paramete, so you actually don't need to use Invoke-Command :)


Kind regards,
Stephan Linke, Tech Support Team


Feb, 2018 - Permalink

Hi Stephan

Thanks, this is working correctly now.

I'm using the Invoke-Command so that I can pass credentials to the remote computer, the Get-Counter cmdlt doesn't appear to have a way of passing credentials.

When PRTG runs the script is it running them as the user configured for the PRTG Probe Service? (ours is running as the Local System account) If it does, what is the minimum permissions an account would need to run the Probe Service on the PRTG Host? EDIT: just remembered I can change the access rights in the Settings for the sensor.

One last question if I may, the performance counter returns values in nanoseconds, I've done some searching and am still looking but is there a way to convert the counter value from nanoseconds to milliseconds? (I've made a change to strip the decimals places from the returned counter by using [int] so I now have the following:

  ForEach-Object {
    $InstanceName = $_.InstanceName
    [int]$Value   = $_.CookedValue
     
  Write-Host
       "<result>"
       "<channel>$InstanceName</channel>"
       "<value>$Value</value>"
       "</result>"

Feb, 2018 - Permalink

Well, you could simply divide it by 1000:

[int]$Value = $_.CookedValue / 1000

That should be it :)


Feb, 2018 - Permalink