What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general.

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
More than 500,000 users rely on Paessler PRTG every day. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags

View all Tags

How can I monitor certified CA certificates with PRTG?



I know I can monitor SSL certificates with a preconfigured sensor in PRTG.

But how can I monitor an active digital CA windows certificate on the machine running the PRTG probe?

certificate custom-script-exe custom-sensor expiry powershell prtg ps1

Created on Jul 20, 2012 12:37:43 PM by  Daniel Zobel [Product Manager]

Last change on Mar 19, 2015 3:42:27 PM by  Martina Wittmann [Paessler Support]

9 Replies

Accepted Answer



This article applies to PRTG Network Monitor 12 or later

Monitoring a Windows CA Certificate

I found a way to monitor certification-expiry that should be useful for you.

Note: You will be able to monitor certificates on the machine running the PRTG Probe only; you cannot monitor certificates on remote machines with this!

Please copy&paste the following script in a file with the extension .ps1 and place it in the Custom Sensors\EXEXML sub directory of your PRTG program directory. In the PRTG web interface, add a new EXE/Script (Advanced) sensor using this script.

The sensor without any parameter returns the expiry time in days of any certificates installed on your probe computer. You can filter the stores by using the -store <your store name> parameter.

It will be usefull for us if you can give us some feedback if and how the sensor works.

# begin of script #

Param( $store='all' )
# To get this script running with PRTGNetworkMonitor you need to enable RemoteSigned-scripting for 32bit-processes. 
# This can be done with running 'c:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy RemoteSigned"' on a system with default paths
# the logic behind this sensor is based on the basics from http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/16/use-powershell-and-net-to-find-expired-certificates.aspx
# Examples of Parameters-string in sensorsettings
#   -store AuthRoot 
# possible values see $stores-variable + 'all' or leave the field empty for default ('all')
# !!! the storenames are casesensitiv !!!
# declare script-wide variables
$script:starttime = Get-Date
$script:table = $null
$script:resultText = "OK"
$stores = @('AddressBook', 'AuthRoot', 'CertificateAuthority', 'My', 'Root', 'TrustedPeople', 'TrustedPublisher')
function main {
switch ($store)
'all' {
foreach($certStore in $stores){
$storeRef = New-Object System.Security.Cryptography.X509Certificates.X509Store($certStore,"LocalMachine")
foreach($certificate in $storeRef.Certificates) {
addCertificate -certificate $certificate -storename $storeRef.name
default {
$storeRef = New-Object System.Security.Cryptography.X509Certificates.X509Store($store,"LocalMachine")
foreach($certificate in $storeRef.Certificates) {
addCertificate -certificate $certificate -storename $storeRef.name
    # add the execution-time to channels
$row = $table.NewRow();
$row.channel = "ExecutionTime"; 
$row.unit = "TimeSeconds"; 
$row.SpeedTime = "Second"; 
$row.float = "1";
$row.ShowChart = "0"; 
$row.ShowTable = "0"; 
$row.Value = "$([Math]::Round((new-timespan $starttime).totalseconds,1))"; 
# forward the generated table to xml-generator and store the result
$retval = $table | New-Xml -RootTag prtg -ItemTag result -ChildItems Channel,Value,Unit,CustomUnit,Warning,Error,speedtime,volumesize,mode,showchart,showtable,float -ResultTag $resultText
write-host $retval 
function addCertificate {
    param($certificate, $storeName)
    $value = ($certificate.notAfter - ($script:starttime)).Days
    if (($script:store -eq 'all') -and ($storeName -ne '')) { $prefix = "$($storeName) - " }  
    if ($value -ne '') {
    $row = $table.NewRow();
        if ($certificate.friendlyName -ne '') {
            $row.channel = "$prefix$($certificate.friendlyName)"; 
        } else {
            $row.channel = "$prefix$($certificate.GetName())"; 
    $row.value = $value
    $row.unit = "Custom"
    $row.customUnit = "Days"
function prepareResultTable {
    # create a table to store the information only if not yet done
    # all available values predefined, in the result only the active values will apear
    if ($script:table -eq $null) {
        $script:table = New-Object system.Data.DataTable "result"
        $col1  = New-Object system.Data.DataColumn channel,string
        $col2  = New-Object system.Data.DataColumn value,string       # a Integer or float value preconverted into a string!
        $col3  = New-Object system.Data.DataColumn unit,string        # BytesBandwidth/BytesMemory/BytesDisk/Temperature/Percent/TimeResponse/TimeSeconds/Custom/Count/CPU (%)/BytesFile/SpeedDisk/SpeedNet/TimeHours
        $col4  = New-Object system.Data.DataColumn customUnit,string
        $col5  = New-Object system.Data.DataColumn warning,string     # 0/1 (no/yes) 0
        $col6  = New-Object system.Data.DataColumn SpeedSize,string   # One/Kilo/Mega/Giga/Tera/Byte/KiloByte/MegaByte/GigaByte/TeraByte/Bit/KiloBit/MegaBit/GigaBit/TeraBit
        $col7  = New-Object system.Data.DataColumn VolumeSize,string  # siehe Speedsize
        $col8  = New-Object system.Data.DataColumn SpeedTime,string   # Second/Minute/Hour/Day
        $col9  = New-Object system.Data.DataColumn Mode,string        # Absolute/Difference
        $col10 = New-Object system.Data.DataColumn ShowChart,string   # 0/1 (no/yes) 1
        $col11 = New-Object system.Data.DataColumn ShowTable,string   # 0/1 (no/yes) 1
        $col12 = New-Object system.Data.DataColumn Float,string       # 0/1 (no integer/yes float) 0
# this function produces a well-formated xml-output out of a given table
function New-Xml
param($RootTag="ROOT",$ItemTag="ITEM", $ChildItems="*", $resultTag, $Attributes=$Null)
Begin {
$xml = "<$RootTag>`n"
Process {
$xml += "  <$ItemTag>`n"
foreach ($child in $_ | Get-Member -Type *Property $childItems)
$Name = $child.Name
        if ("$($_.$name)" -ne "")  {
    $xml += "    <$Name>$($_.$Name)</$Name>`n"
$xml += "  </$ItemTag>`n"
End {
        if ([string]$resultTag -ne $false) {
            $xml += "  <text>$resultTag</text>`n" 
$xml += "</$RootTag>`n"
# print a xml-errormessage
function printErrorXml($errortext = $script:resultText) {
    $errorXml = "<prtg>`n"
    $errorXml += "  <error>1</error>`n"
    $errorXml += "  <text>$errortext</text>`n"
    $errorXml += "</prtg>`n"
#end of script #

Created on Jul 20, 2012 12:42:41 PM by  Daniel Zobel [Product Manager]

Last change on Aug 29, 2012 11:05:59 AM by  Daniel Zobel [Product Manager]



i have a Problem with this Script, i have copy it to a ps1 script an load it in new sensor exe/XML. But when i activate the ne sensor i get a failor:

Error reading Response: Invalid XML (missing/prtg)

Whats wrong?

Thanks a lot

Created on Jul 7, 2015 1:55:09 PM




what happens when you run the script manually? As this is a powershell script, did you set the Powershell execution policy accordingly?

best regards.

Created on Jul 7, 2015 2:58:21 PM by  Torsten Lindner [Paessler Support]



Hello, thanks a lot for the script. How can I check the certificats on other servers then the probe server. And it is possibel to create some failure limits for the sensor?

best regards

Created on Apr 7, 2016 7:59:21 AM



That would require the script to be invoked on the remote host (via Invoke-Script). A bit of work is necessary then, I'm afraid. Limits can be applied within the channel settings just like for any other sensor :)

Created on Apr 7, 2016 2:39:17 PM by  Stephan Linke [Paessler Support]




I have a script which will print certificate name and expiry days in Issued certificates from a Certificate Authority server. can someone help me in printing the output in xml format so that we can monitor in PRTG

#############  Starting Script ####################
function get-ExpiringCerts ($duedays=60,$CAlocation="CAServer\Some Root CA") {
  $certs = @()
  $now = get-Date;
  $expirationdate = $now.AddDays($duedays)
  $CaView = New-Object -Com CertificateAuthority.View.1
  $index0 = $CaView.GetColumnIndex($false, "Issued Common Name")
  $index1 = $CaView.GetColumnIndex($false, "Certificate Expiration Date")
  $index2 = $CaView.GetColumnIndex($false, "Issued Email Address")
  $index3 = $CaView.GetColumnIndex($false, "Certificate Template")
  $index4 = $CaView.GetColumnIndex($false, "Request Disposition")
  $index0, $index1, $index2, $index3, $index4 | %{$CAView.SetResultColumn($_) }

  # CVR_SEEK_EQ  1
  # CVR_SEEK_LT  2
  # CVR_SEEK_GT  16

  $index1 = $CaView.GetColumnIndex($false, "Certificate Expiration Date")

  # brief disposition code explanation:
  # 9 - pending for approval
  # 15 - CA certificate renewal
  # 16 - CA certificate chain
  # 20 - issued certificates
  # 21 - revoked certificates
  # all other - failed requests

  $RowObj= $CAView.OpenView()

  while ($Rowobj.Next() -ne -1){
    $Cert = New-Object PsObject
    $ColObj = $RowObj.EnumCertViewColumn()
    do {
      $current = $ColObj.GetName()
      $Cert | Add-Member -MemberType NoteProperty $($ColObj.GetDisplayName()) -Value $($ColObj.GetValue(1)) -Force
    } until ($ColObj.Next() -eq -1)
    Clear-Variable ColObj
    $datediff = New-TimeSpan -Start ($now) -End ($cert."Certificate Expiration Date")

    "Certificate " + $cert."Issued Common Name" + " will expire in " + $dateDiff.Days + " days at " + $cert."Certificate Expiration Date"
    #"Send email to : " + $cert."Issued Email Address"
  $CaView = $null

get-ExpiringCerts -duedays 365 -CAlocation "CAServer\Some Root CA"

######## Ending Script #############

Regards Madhusudhan Kasturi

Created on Jan 26, 2021 8:53:05 PM

Last change on Jan 27, 2021 6:27:25 AM by  Felix Wiesneth [Paessler Support]




The output has to be as expected by PRTG. You can find the proper output syntax in your Webinterface under "Setup > PRTG API > Custom Sensors" or within our online manual. This article might help as well.

Created on Jan 28, 2021 7:15:56 AM by  Timo Dambach [Paessler Support]



Hello, Thanks for the reply I am very much new to powershell and xml. Can anyone of you help me in providing script similar to above.

Thanks in advance

Created on Feb 1, 2021 8:57:23 PM



Hello, maybe someone out of the community might be able to help. Currently we -Paessler - can only offer general support for PRTG. Regarding customization and custom sensors/scripts we can only offer very limited support: We can of course provide hints, but we do not provide or adjust custom scripts. Thank you for understanding.

Created on Feb 2, 2021 11:55:12 AM by  Timo Dambach [Paessler Support]

Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.