The Extreme Basics of PRTG Custom Sensors with PowerShell

If you’re not already familiar with PRTG, I recommend that you find a spare machine someplace to set up the demo and give it a try. As you might have read in some of our previous posts, we’ve deployed PRTG to great effect on several of our clients’ networks. From a high level, PRTG is pretty standard network/device monitoring fare. There’s plenty of comparisons to be made between PRTG, SolarWinds, WhatsUp Gold, and so forth, but today I’m going to discuss the one feature of PRTG that has pushed it ahead of the pack: Custom Sensors.
Out-of-the-box, PRTG supports a pretty wide gamut of sensors and should be able to give you reasonably comprehensive monitoring of most network devices. To get beyond the data that the packaged sensors provide, you can roll-your-own custom sensors. Custom sensors for PRTG are very simple: a script or a program gathers some data and returns it back to PRTG in a structured XML format. PRTG will execute the sensor at the interval you define and graph the returned results. We’ve had good success writing sensors of this type in PowerShell, which is what I’m going to cover here today – but some of this can apply to any compiled executable as well.

Step One: Install PRTG

Ensure that you’ve got it up and running and graphing data, and that you can reach the PRTG web GUI using your web browser. Firefox and Chrome or the very latest versions of IE (9, 10) strongly recommended.

Step Two: Fix the PowerShell execution policy

This one tends to get overlooked. On a 32-bit server, this is simple: open a PowerShell prompt with admin rights and enter Set-ExecutionPolicy RemoteSigned (other options: “AllSigned” if your scripts are all signed with Authenticode certificates, or “Unrestricted” if you just want to disable execution preventions across the board). However on 64-bit hosts (which is honestly the only architecture I’ve ever installed the PRTG core server on), there’s an extra step: you need to set the 32-bit PowerShell execution policy, rather than the native 64-bit PowerShell policy..
  • Method One: locate the”Windows PowerShell (x86)” shortcut in the start menu and set the execution policy there (Set-ExecutionPolicy RemoteSigned).
  • Method Two: run this command to open a powershell prompt, and then set the execution policy using that prompt: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe

Step Three: Install your custom sensor

PRTG gives a drop-down menu in the PRTG GUI that lists the contents of the EXEXML directory (c:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\). Save your custom scripts to this folder so you’ll be able to select them in the GUI in the next step. I’ll go into detail about proper formatting in a bit.

Step Four: Add your new sensor to a device

Presumably you’ve got some specific purpose intended for your custom sensor – possibly some esoteric metric that some gizmo on your network is capable of reporting, but it does so by some arbitrary, partially-formatted method. You’ve possibly already added this device to PRTG, and maybe even have some other sensors configured for it – ping, SNMP traffic, etc. Select the device choose “Add Sensor.” In the massive list of sensors you’re presented, locate “EXE/Script Advanced”. You can pare down the list by typing “exe” in the search box. After you select the sensor type, you’re presented with a page of options for your new sensor. The only option on this page that cannot be changed after adding the sensor is the EXE/Script field – which is where you select the script you saved in step three. Once you’ve picked the right script on the drop-down box, you can save your sensor and watch it collect data for you.
And that’s it: you’ve got a custom sensor.

Appendix A: Output Formatting

The EXE/Script Advanced sensor type expects the data to be returned in an XML format. This is the “minimum example” from the PRTG API Documentation:
<prtg>
<result>
<channel>First channel</channel>
<value>10</value>
</result>
<result>
<channel>Second channel</channel>
<value>20</value>
</result>
</prtg>
This example returns two channels back to PRTG – one creatively called “First channel,” and the second called “Second channel.” Each of these channels contain a numeric value (which is what PRTG will graph). In addition to these required fields, each of result block can define the units that the data is returned as, state if the returned value is a counter, set the sensor to a warning state, and set defaults for displaying the data in the graphs or tables, upper and lower warning and error limits, as well as messages when limits are reached. Note that these last options only set defaults when the sensor is first added – if your sensor doesn’t report them correctly on the first scan, they won’t be read on subsequent scans (such as when you update the sensor’s script file). Full information about all of these values is available in the PRTG API Documentation.
One of my colleagues at Lockstep, Brian Addicks, has put together a PowerShell module that contains a series of functions to facilitate working with the PRTG API, as well as one function to ease working with this output format: Set-PrtgResult. This function simplifies the process of generating the final XML format for your sensor to this:
$XMLOutput = “<prtg>`n”

$XMLOutput += Set-PrtgResult “Disk Total” $TotalDisk “Gbyte”


$XMLOutput += Set-PrtgResult “Disk Free” $FreeDisk “Gbyte”


$XMLOutput += Set-PrtgResult “Disk Free %” $PercentFree “Percent”


$XMLOutput += “</prtg>”
Additionally, there’s two things that go outside of the result channels: Text messages and Error states. Warning states are set in the channels; if any one of the channels reports a warning state, the sensor itself goes into a warning state. Error states on the other hand are set outside of the result blocks in the code. Additionally, a sensor in an error state may not record data. *

Appendix B: Script Parameters

PowerShell scripts, much like PowerShell Advanced Functions, can accept parameters using a param() statement at the beginning of the file. You can and should use this capability to easily pass positional parameters from PRTG to your script. PRTG’s API goes into detail about thecommand line placeholders available in the PRTG API Documentation, but the one value I find myself using more than any other is %host’. This returns the value from the “IPv4 Address/DNS Name” field from the parent device of the sensor.
Make sure you single-quote parameters that could potentially have spaces or other breaking characters.

Appendix C: Troubleshooting

Unless you’re an incredible, experienced professional programmer who writes perfectly bug-free and error-handled code, there’s a better-than-average chance that you’re going to write a script that eventually fails to return data as expected. Helpfully, PRTG will probably give you an error messages that give you absolutely no help in finding the cause:
  • Error reading response: missing /prtg
  • Error reading response: XML Parser mismatch: Wanted </<<<>, got </prtg>
… or, it may just time out and report that no data was received.
You can of course greatly diminish pains in troubleshooting by doing lots of error-handling in your code and use the <error></error> element in your output to return a useful message about what is wrong. If you haven’t gotten that far, you can also just review the raw return value of the script. On your sensor settings page, there is an option titled “EXE Result” that is by default set to “Discard EXE result”. You can change this to “Write EXE result to disk (Filename: “Result of Sensor [ID].txt”)” and then go watch C:\ProgramData\Paessler\PRTG Network Monitor\Logs (Sensors) for the text file with the proper sensor ID in the filename. This file will contain the full raw output of your script, complete with any errors.
Some things to keep in mind when you’re troubleshooting a new sensor:
  • The script doesn’t necessarily execute as you – it executes using either the scope of the PRTG service (be that on the probe or the core server) which you can of course change using the Windows Services tool, or as the user defined in the credentials for the device.
  • PRTG always executes all powershell scripts in 32-bit powershell.
  • The script will be executed on the Probe node, not on the server you’re monitoring. It’s absolutely possible to write scripts that remote into the monitored machine to perform some check or task, but if the check or task involves the monitored server contacting another server, you’re going to need to research the double hop limitation.