PRTG - PS Custom Sensor

Wenn Sie einen PRTG - Custom Sensor selbst entwickeln wollen, dann ist PowerShell eigentlich eine sehr flexible Plattform. Sie können schnell und dennoch leistungsfähig eine Logik umsetzen, ohne eine EXE kompilieren zu müssen oder mit CMD/Batch-Skripten zu hantieren. Für viele Aufgaben gibt es sogar fertige Module. Aber die Ausführung von PowerShell durch eine PRTG-Probe unterliegt einigen Besonderheiten, auf die ich hier eingehe.

CMD-Starter

Ich nutze oft und viel die Powershell aber wie ich in den folgenden Abschnitten beschreibe, ist es nicht immer einfach die richtige PowerShell durch die PRTG-Probe als PS1-Datei starten zu lassen. Daher nutze ich lieber den Weg, eine CMD-Datei einzubinden, die dann die gewünschte PowerShell startet. Allerdings müssen Sie dann natürlich selbst die Parameter mit übergeben.

@echo off
IF "%1"=="" GOTO noparam
"C:\Program Files\PowerShell\7\pwsh.exe" -Noninteractive -nologo -ExecutionPolicy Unsigned -File %1 %2 %3 %4 %5 %6 %7 %8 %9
return %ERRORLEVEL%
goto end

:noparam
echo ^<?xml version="1.0" encoding="UTF-8" ?^>
echo ^<prtg^>
echo    ^<error^>1^</error^>
echo    ^<text^>No Script specified^</text^>
echo ^</prtg^>

:end

Als ersten Parameter muss ich natürlich das Skript mit kompletten Pfad angegeben werden, z.B. "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\prtgtest.ps1" und danach die weiteren Parameter

Mittlerweile bin ich davon abgekommen, ein generische Skript mit Parametern zu starten, was auch wieder eine Fehlerquelle sein kann, sondern ich lege einfach zum Sensor eine passende CMD-Datei an, die diesen Sensor direkt startet

PowerShell und PWSH

Es gibt neben der "alten" PowerShell bis zur Version 5 schon länger auch eine neue auf ".NET-Core" basierte PowerShell ab Version 6. Beide sehen sehr ähnlich aus aber die neuere Version ist nicht auf Windows beschränkt, sondern kann z.B. auch auf Linux genutzt werden. Allerdings gibt es noch nicht alle Module der alten PowerShell schon für die neue Version und eine Interaktion mit COM-Objekten und WMI ist nur über ein Kompatibilitätslayer möglich.

Daher scheinen viele Administratoren und Skripte immer noch mit der alten PowerShell zu laufen. Einige Commandlets der neuen PowerShell Core-Version haben aber neue und nützliche Parameter, die Sie aber dazu verleiten, vielleicht diese zu nutzen. Sie können die tun aber denken Sie daran, dass die PRTG Probe weiterhin nur die "alte" PowerShell" aufruft und sie sich daher eine Brücke bauen müssen.

Execution-Policy

Wenn PRTG ihre Skripte nicht ausführen kann, dann liegt das meist an der ExecutionPolicy der PowerShell. Um lokal liegende Skripte ausführen zu lassen, muss die Richtlinie auf "Unrestricted" stehen oder sie müssen das Skript signieren. Beachten Sie auch, dass die PRTG Probe die PowerShell 2-5 und nicht 6/7 startet und auch nur 32bit nutzt. Die Default-Einstellungen für von PRTG gestarteten PS1-Dateien muss in der richtigen PowerShell gesetzt werden. Im Logfile finden Sie ansonsten folgendes:

File C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\sample.ps1 cannot be loaded
 because the execution of scripts is disabled on this system
. Please see "get-help about_signing" für more details.
At line:1 char:2
+ & <<<< 'C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\sample.ps1' ; exit $LASTEXITCODE
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

Sie müssen die Execution-Policy zumindest aus RemoteSigned oder unsicherer stellen, damit die Skripte überhaupt gestartet werden.

REM Setzen der Policy für 32bit PowerShell
%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\PowerShell.exe "Set-ExecutionPolicy RemoteSigned"

REM Anzeige der Policy für 32bit PowerShell
%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\PowerShell.exe "Get-ExecutionPolicy -list"

Sie sollten natürlich auch prüfen, woher Sie die PS1-Datei kopiert haben. Gerade beim Download aus dem Internet passiert es schnell, dass die Datei noch die "Zoneneinstellung:Internet" hat und daher geblockt ist. Ggfls. müssen Sie die Datei über die Eigenschaften im Explorer oder mittels "Unblock-File" freischalten.

Unblock-File C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\sample.ps1

Es wäre nett, wenn die PRTG Probe beim Start des passenden PowerShell-Prozess einfach die Default-ExecutionPolicy überschreiben würde. Das geht nämlich einfach. Siehe PowerShell ExecutionPolicy. Tut PRTG aktuell aber leider nicht

32bit Probe und 64bit Skripte

Alle Exchange Administratoren nutzen schon seit Exchange 2007 die PowerShell und natürlich die 64bit Version und entsprechende AddOns. Die erste Falle, in die sie tappen können, ist daher die 32bit PowerShell. Anfangs war PRTG immer nur eine 32bit Version aber mittlerweile installiert Paessler auf 64bit Systemen mit 6GB oder mehr Ram automatisch die 64bit Version.

Das Programmverzeichnis ist dabei auch bei der 64-bit Version unter "C:\Programme (x86)\PRTG Network Monitor" zu finden.

Im Taskmanager ist gut zu sehen, welche Komponenten mit 64bit laufen:

Die "PRTG Probe.exe", welche für die Ausführung der Skripte zuständig ist, ist weiterhin ein 32bit Prozess. Ich habe daher ein kleines Skript-Script angelegt und als Sensor eingebunden:

param (
	$outfile = "c:\temp\prtgtest.txt"
)

"START: PRTG Test" | out-file $outfile
"Get-Variable--------------" | out-file $outfile -append
Get-Variable | out-file $outfile -append
"PSVersionTable--------------" | out-file $outfile -append
$PSVersionTable | out-file $outfile  -append
"64bitProcess --------------" | out-file $outfile -append
"64bitProcess : $([System.Environment]::Is64BitProcess)" | out-file $outfile -append
"END: PRTG Test" | out-file $outfile -append
"<?xml version=""1.0"" encoding=""UTF-8"" ?>
<prtg>
   <result>
      <channel>MinuteOfTime</channel>
      <value>$((get-date).minute)</value>
      <float>0</float>
   </result>
   <text>Text from prtgtest from $(get-date) with PowerShell</text>
</prtg>
"

In dem Beispiel landet in C:\Temp eine Text-Datei in der neben vielen anderen Werten folgendes steht:

PSVersionTable--------------

Name                           Value
----                           -----
PSVersion                      5.1.22621.963
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.963
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1


64bitProcess --------------
64bitProcess : False
END: PRTG Test

Das Powershell-Skript ist ein 32bit Prozess einer PowerShell 5. Wenn ich also 64bit Code ausführen möchte oder Code der neuen PowerShell Core nutzen will, muss ich mir ein Vehikel bauen.

Wenn Sie eine 64bit PowerShell oder die PWSH-Shell benötigen, müssen Sie diese über die 32bit PS1-Datei oder eine CMD-Starter-Datei aufrufen.
Siehe auch 32/64bit auf PS Beispiele und http://www.paessler.com/knowledgebase/en/topic/15043-force-64-bit-PowerShell

c:\windows\sysnative\windowsPowerShell\v1.0\PowerShell.exe `
    -file "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\64bitsensor.ps1"

Über den gleichen Weg können Sie natürlich auch die PWSH aufrufen

C:\Program Files\PowerShell\7\pwsh.exe `
    -File "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\64bitsensor.ps1"

Tipp:
Sie können auch auf 64bit Windows Skripte in einer 32bit Welt interaktiv starten, indem Sie eine 32bit CMD über den Aufruf von "%windir%\SysWoW64\cmd.exe" starten.

Ich würde mir schon wünschen, wenn man bei der Definition des Sensors die Skriptumgebung (CMD, PowerShell32, PowerShll64, PWSH32/PWSH64/PHP/Python etc.) auswählen könnte und die entsprechenden Dateien (CMD, PS1, PHP, Python) dann angezeigt würden.

Write-Host und STDOUT

Die Rückgabe von Ergebnissen an PRTG erfolgt entweder als Einzeiler oder als XML/JSON-Struktur, die vom Skript einfach "ausgegeben" wird. Hier gibt es aber nun mehrere Ausgabemöglichkeiten. Hier drei Optionen:

# Einfach einen String nach STDOUT senden
"Ausgabe1"

# Einfach einen String mit Out-Host nach STDOUT senden
"Ausgabe2" | out-host

# Eine Ausgabe auf die Konsole senden
Write-Host "Ausgabe3"

# Ausgabe von Verbose
Write-Verbose "Ausgabe4"

# Ausgabe eines Errorboxp1
Write-Host "Ausgabe5"

Es werden die  Ausgaben 1,2,3 und 5 von PRTG ausgewertet. Die "Wirte-Verbose" kommt regulär nicht mit. Das bedeutet aber auch, dass Sie keine Debug-Ausgaben mit "Write-Host" auf die Konsole ausgeben sollten, um das Parsen der Ausgabe nicht zu erschweren.

Protipp:
Prüfen Sie die Variable %prtg_version%, um zu erkennen, wann das Skript von der PRTG-Probe gestartet wurde und passen Sie entsprechend die Ausgabe an.

Logging und PSDebug

Skripte, die "still" im Hintergrund laufen, sollten immer eine Diagnose-Funktion haben. Disk-I/O ist günstig und prüfen Sie, ob das Skript nicht die klassischen Ausgaben von "Write-Host" vielleicht in eine Datei oder einen Syslog-Server o.ä. umleiten kann. Sie können zwar auch in PRTG ein Logging einschalten, aber dann werden alle Ausgaben einfach nur nach "C:\ProgramData\Paessler\PRTG Network Monitor\Logs\sensors" geschrieben. Da PRTG aber den kompletten Output auswertet, stört eine ausführliche Ausgabe das Parsen der Ergebnisse.

Ein häufiger Fehler sind vertippte Variablen, die dann immer "$null" sind. Dies können Sie erkennen, indem Sie PowerShell anweisen, dass jede Variable vorab definiert sein muss

Set-PSDEBUG -Strict

Diese Option dürfen Sie im Skript nicht verwenden. Sie können Sie gerne aktivieren, wenn Sie das Skript außerhalb von PRTG zum Test aufrufen, aber innerhalb von PRTG kommt es zu folgenden Fehler, der in der Art des Aufrufs durch PRTG begründet ist.

# Aufruf der PowerShell von PRTG früher
'PowerShell.exe -Noninteractive -Command "&'''+exepath +'''" ' + params+ '; exit $LASTEXITCODE';
# Aktueller Aufruf der PowerShell über Ausgabe von $MyInvocation.line  ermittelt
if ($PSVersionTable.PSVersion.Major -ge 5) { 
   Import-Module Microsoft.PowerShell.Management; 
   Import-Module Microsoft.PowerShell.Utility
};
&'C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\samplescript.ps1' ; 
exit $LASTEXITCODE

Beide Aufrufe senden am Ende aber den Inhalte "$LASTEXITCODE". Die Variable ist aber nicht definiert und damit liefert die PowerShell mit strikter Prüfung den folgenden Fehler:

The variable '$LASTEXITCODE' cannot be retrieved because it has not been set.
At line:1 char:102
+ &'C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\cpuload.p
s1' ; exit $LASTEXITCODE <<<< 
    + CategoryInfo          : InvalidOperation: (LASTEXITCODE:Token) [], Runti 
   meException
    + FullyQualifiedErrorId : VariableIsUndefined

PSSession und Module

Die meisten Erweiterungen von PowerShell erfolgen über entsprechende Module, die sie mit "Install-Module" sehr einfach auf einem System installieren und dann in ihre Skripte integrieren können. So gibt es

Module für Exchange Online und Microsoft Teams, welches mit "Connect-ExchangeOnline" oder "Connect-Microsoftteams" auch einfach zu verbinden sind. Für die automatische Nutzung können Sie hier natürlich keine Benutzernamen/Kennworte oder gar 2FA einsetzen, sonder müssen Sie über App-Permissions gehen

Ältere Module und Dienste werden noch per "Import-PSSession" eingebunden. Es ist wichtig am Ende eines Skript unbedingt eventuell eingebundene PSSessions auch wieder sauber zu entfernen. bei einer Exchange Remote Session bleiben sonst ca. 4KB Temp-Files je Aufruf in C:\windows\temp übrig was sich pro tag schnell auf 1 GB summiert. siehe auch PS Remote

Powershell 7 und 64bit

Seit einiger Zeit gibt es aber nun die PowerShell 7 (Core), die auf dem .NET-Core-Framework basiert. Sie wird die bisherige auf dem .NET-Framework basierende PowerShell 2-5 ersetzen. Aus meiner Erfahrung ist die PowerShell 7 deutlich flotter und auch umfangreicher, z.B. mit Klassen ausgestattet. PRTG ist selbst aber ein 32bit-Programm und startet daher per Default auch nur eine 32bit PowerShell 2.0. Das ist ungeschickt, wenn manche Module benötigen einer 64bit Powershell und einige Skripte funktionieren mit Powershell 7 oder höher deutlich besser.

Leider hat Microsoft keine eigene Dateierweiterung wie z.B. ".ps7" mit der neuen Powershell verknüpft und PRTG bietet im Jun 2020 leider noch keine Option an, den Powershell-Handler auszuwählen. PRTG orientiert sich einfach an den Standard Betriebssystem-Verbindungen:

.CMD = cmdfile = Windows Command Script
.BAT = batfile = "Windows Batch File"
.PS1 = Microsoft.PowerShellScript.1

Da ich die Erweiterung ".PS1" ungern global auf die neue Powershell 7 umlenken möchte gibt es eigentlich nur drei Varianten:

  • PS7 über BAT/CMD starten
    Ich kann natürlich einfach eine CMD-Datei in das Verzeichnis legen, die dann eine PowerShell 7 startet und als Parameter das Skripte und Skript-Parameter mitgeben.
  • PS7-Erweiterung einführen
    Eine andere freche Option wäre einfach die Definition einer eigenen "PS7-Erweiterung". Allerdings ignoriert PRTG die Erweiterung "ps7" einfach. Er PRTG erlaubt nur die Auswahl von COM, EXE, BAT, VBS und PS1 an.
  • PS1 als EXE einpacken
    Es sollte auch möglich sein, ein PowerShell Skript in eine EXE zu verwandeln, die PWSH nutzt. Bislang habe ich in der TechNet Gallery aber nur eine Lösung für PowerShell gefunden
    https://gallery.technet.microsoft.com/PS2EXE-Convert-PowerShell-9e4e07f1. Aber es ist recht einfach, einen "Powershell Host" zu schreiben, der Befehle ausführt.

Solange also in der Sensor-Auswahl von PRTG nicht auch der Handler zwischen "powershell.exe" und "pwsh.exe" umgestellt werden kann, bleibt nur der Weg über ein CMD-File. Ich lasse PRTG also eine CMD-Datei starten, die dann die eigentliche PowerShell ausführt. Hier ein Beispiel einer solchen CMD-Datei:

REM Startet das PS1-Skript mit der richtigen Powershell und Parametern

"C:\Program Files\PowerShell\7\pwsh.exe" ^
   -nologo ^
   -NonInteractive ^
   -command "& ""C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\get-fritzmactable.ps1"" -FBKennwort:""geheimeskennwort"" -prtg"

Diese wenigen Zeilen können Sie als CMD-Datei ablegen und entsprechend aufrufen lassen. Sie entstammt dem Beispiel Get-FritzMACTable, welches mit der PowerShell 7 arbeitet und so einfach unter PRTG aufgerufen werden kann.

Error Handling

Rechnen Sie immer damit, dass ein Sensor einen Fehler hat. Eine globale Try/Catch Schleife kann das abfangen

try{
   $totalprocesses = (Get-Process).count

   Write-Host "<prtg>"
   Write-Host "  <result>"
   Write-Host "    <channel>ProcCount</channel>"
   Write-Host "      <value>$totalprocesses</value>"
   Write-Host "      <unit>Number</unit>" 
   Write-Host "    <float>0</float>" 
   Write-Host "  </result>"
   Write-Host "</prtg>"
}

catch{
   Write-Host "<prtg>"
   Write-Host "  <error>1</error>"
   Write-Host "  <text>An Error accured</text>"
   Write-Host "</prtg>"
}

Aber dann geht es relativ schnell, einen entsprechenden Sensor zu schreiben.

Achtung
PRTG wertet sowohl ausgaben über STDOUT, d.h. die PowerShell Pipeline als auch "Write-Host" aus, während z.B. Start-Transcript die Ausgaben von Write-Host nicht erfasst.. Wer also "Bildschirmausgaben" zu diagnosezwecken nutzt, muss diese beim Start durch PRTG unterdrücken. Ich starte speziell längere Skript nicht mehr durch PRTG sondern den Taskplaner und sende die Ergebnisse per PRTG - HTTP Push-Sensoren an PRTG. Dann kann ich den Aufruf auch von anderen Systemen ohne PRTG-Probe machen.

Invoke-Webrequest

Der beliebte PowerShell-Befehl zum Download von Webseiten funktioniert nicht im PRTG-Sensor. Wenn Sie in einem Sensor eine Webseite mit "Invoke-Webrequest" abfragen wollen, dann denken Sie daran, dass die Umgebung "beschränkt" ist.  Invoke-Webrequest nutzt IE-Module um den Inhalt zu rendern. Das ist aber bei Sensoren meist nicht erforderlich und funktioniert auch nicht. Der Parameter "-UseBasicParsing" löst das Problem.

Default Verzeichnis "C:\Windows\SysWOW64"

Wenn Sie im PowerShell eine Ausgabe z.B. mit export-clixml o.ä. nach ".\dateiname.ext" schreiben, dann landet dies im Verzeichnis "C:\Windows\SysWOW64". Wenn ein Script also Dateien speichern will, dann sollten Sie einen Pfad vorgeben.

Berechtigungen

Eine normale PowerShell kann schon viele Daten ermitteln. Es gibt aber Add-ons (z.B.: Exchange), die bestimmte Abfragen z.B. im Hintergrund doch per WMI durchführen und dazu lokale Admin sein müssen. Das kann Sie betreffen, wenn die Probe als LocalSystem läuft und Sie beim Sensor ein abweichendes Benutzerkonto angegeben haben.

Laufzeitumgebung

Ich habe einfach mal ein Skript erstellt, welches einige Daten exportiert, um die Laufzeitumgebung zu ermitteln.

get-variable | Export-Clixml .\test.variable.xml
$host  | Export-Clixml .\test.host.xml
$input | Export-Clixml .\test.input.xml
Get-Childitem env: | Export-Clixml .\test.env.xml

Hier die Ausgabe von $host

Name             : ConsoleHost
Version          : 4.0
InstanceId       : bb3422f2-bd3a-49f2-a534-444782199be9 
uI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : de-DE
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

Und hier die Ausgabe der Variablen

Name                           Value
----                           -----
$
?                              True
^
args                           {}
ConfirmPreference              High
ConsoleFileName
DebugPreference                SilentlyContinue
Error                          {}
ErrorActionPreference          Continue
ErrorView                      NormalView
ExecutionContext               System.Management.Automation.EngineIntrinsics
false                          False
FormatEnumerationLimit         4
HOME
Host                           System.Management.Automation.Internal.Host.InternalHost
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple
MaximumAliasCount              4096
MaximumDriveCount              4096
MaximumErrorCount              256
MaximumFunctionCount           4096
MaximumHistoryCount            4096
MaximumVariableCount           4096
MyInvocation                   System.Management.Automation.InvocationInfo
NestedPromptLevel              0
null
OutputEncoding                 System.Text.ASCIIEncoding
PID                            3084
PROFILE                        WindowsPowerShell\Microsoft.PowerShell_profile.ps1
ProgressPreference             Continue
PSBoundParameters              {server}
PSCommandPath                  C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\prtg-excasUser.ps1
PSCulture                      de-DE
PSDefaultParameterValues       {}
PSEmailServer
PSHOME                         C:\Windows\SysWOW64\WindowsPowerShell\v1.0
PSScriptRoot                   C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML
PSSessionApplicationName       wsman
PSSessionConfigurationName     http://schemas.microsoft.com/PowerShell/Microsoft.PowerShell
PSSessionOption                System.Management.Automation.Remoting.PSSessionOption
PSUICulture                    en-US
PSVersionTable                 {PSRemotingProtocolVersion, BuildVersion, PSCompatibleVersions, PSVersion...}
PPWD                            C:\Windows\system32
server                         nawex001
ShellId                        Microsoft.PowerShell
StackTrace
true                           True
VerbosePreference              SilentlyContinue
WarningPreference              Continue
WhatIfPreference               False

Leider setzt PRTG per Default keine eigenen Variablen, die dem Skript einen Hinweis auf die Laufzeitumgebung geben. Aber eine einfache IF-Abfrage auf "PSScriptRoot" ist meist ausreichend:

if ($PSScriptRoot.EndsWith("EXEXML")) {
    write-host "Check-ADFS: Assume PRTG EXEXML-Mode"
}
else {
    Set-PSDEBUG -strict  # enable strict variable checking. Not usable with PRTG
}

Sie können aber die PRTG-Einstellungen in der Konfiguration aktivieren. Diese sind per Default inaktiv aber können als Platzhalter bei der Parametrisierungen mit übergeben werden. Siehe dazu auch https://prtg.paessler.com/api.htm?Username=demo&password=demodemo&tabid=7) Wenn Sie aber folgende Option aktivieren, dann werden die Parameter aber als Umgebungsvariablen gesetzt.

Dann finden sich auch die von PRTG gesetzten Werte in Variablen:

Achtung:
Über den Weg könnte ein Sensor auch Kennworte ausleiten oder Kennworte erscheinen im LOG/Trace-File.
Die IP-Adresse bzw. den Hostnamen des Device können Sie einfacher als Parameter mit "%host" übermitteln.

prtg_device                    PRTGDEVICE
prtg_deviceid                  2020
prtg_groupid                   2171
prtg_host                      PRTGDEVICE.msxfaq.de
prtg_linuxpassword
prtg_linuxUser
prtg_name                      SENSORNAME
prtg_primarychannel            2
prtg_probe                     PROBENAME
prtg_probeid                   1
prtg_sensorid                  2089
prtg_snmpcommunity             public
prtg_URL                       https://prtg.msxfaq.de/
prtg_version                   13.4.7.3706
prtg_windowsdomain             MSXFAQ
prtg_windowspassword           DeMoPass
prtg_windowsUser               Administrator

Diese Werte können per "$ENV" dann natürlich auch einfach abgefragt werden. Paessler selbst ist hier sehr vorsichtig und schaltet diese Option per Default nicht ein, da so ein Script natürlich auch die Credentials ausgeben könnte.

Achten Sie daher genau darauf, wenn ein CustomSensor diese Daten in der Form von ihnen bekommen möchte.

Variable Description

prtg_version

The version number of your PRTG installation

prtg_URL

The IP address/DNS name of your PRTG installation

prtg_primarychannel

The ID of the sensor's current primäry channel (1 if not set)

AuthorizationManager check failed

Manchmal verweigert Windows den Start des PowerShell-Skripts. Die Ursachen können Vielfältig sein.

& : AuthorizationManager check failed.
At line:1 char:102
+ ... l.Utility};&'C:\Program Files (x86)\PRTG Network Monitor\custom senso ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

So 100% habe ich noch nicht rausgefunden, woran es lag aber Windows scheint zu prüfen, ob die Datei "sauber" ist und da fallen mir folgende Dinge ein

  • Aufruf per UNC-Pfad
    Vermeiden Sie bitte aus einem PS1-Skript heraus andere Module oder Teile über einen UNC-Pfad zu starten. Dieser andere Code kommt aus Sicht der "Sicherheit" von einem "remote Server" und je nach Execution Policy und IE Zonen-Einstellung ist dies möglich oder nicht
  • Datei-Zoneneinstellung
    Wenn Sie eine PS1-Datei aus dem Internet herunterladen oder von einem UNC-Pfad kopieren, dann wird auch wieder die Zoneneinstellung übernommen und die PowerShell kann sich daran stören. Ein Klick auf die Eigenschaften der Datei sollte ihnen das zeigen.
  • PowerShell Profil $PROFILE
    Öffnen Sie die PowerShell und schauen Sie sich den Inhalt der Variable $PROFILE an. Sie verweist in der Regel auf eine PS1-Datei, die die PowerShell automatisch beim Start lädt. Die Datei ist normalerweise nicht vorhanden. Eine leere Datei ist problematisch und man sollte sie löschen oder zumindest ein Zeile mit einem "#" (Kommentar) addieren. Es könnte auch sein, dass diese Datei ebenfalls über die Zoneneinstellungen blockiert wird, z.B. weil das Profil von einem Netzwerklaufwerk (Roaming) kommt oder anderweitig problemtisch ist?

Damit sollten die beiden wesentlichen Blockaden zu finden sein. Es könnte aber weitere geben, die sie analysieren müssen. Zuerst würde ich mit NOTEPAD einfach eine PS1-Datei anlegen, die einfach nur eine Ausgabe z.B. in eine Datei schreibt, eine Ausgabe zurück gibt und von PRTG gestartet wird. Wenn das geht, dann ist der Aufruf generell möglich. Nehmen Sie dann den Code aus der anderen PS1-Datei und übernehmen Sie ihn über die Zwischenablage in die gerade angelegt Datei und prüfen Sie, ob er ausgeführt wird.

Wenn sie so noch nicht weiter kommen, dann ist vielleicht Procmon (Sysinternals) eine Hilfe zu sehen, was die PRTG-Probe macht und was Windows verhindert.

Parameterübergabe

Gerade wenn sie in einem Skript mehrere Module zusammen gefasst habe oder das gleiche Skript für mehrere Ziele eingesetzt wird, sind die Parameter unersetzlich. Sie können damit aus PRTG heraus Werte an den Sensor übergeben.

Damit die Übergabe aber funktioniert, muss im Skript auch der "Param"-Bereich beachtet werden. Wenn Sie am Anfang des Skripte einen "PARAM"-Bereich haben, dann matched die PowerShell die angegebenen Parametern auf die Felder. Nur Named Parameter, die nicht "gefunden werden, landen dann in der Variable $ARGS. Angenommen Sie haben folgenden Parameterkopf:

param (
   [string]$param1= "Wert1",
   [string]$param2= "Wert2"
)

Und übergeben folgende Parameter:

-param2 'test' -param3 'wert3'

Früher habe ich die Werte mit einem Doppelpunkt hinter dem Parametername übergeben. Das scheint aber seit PRTG 18.2.39 (April 2018) nicht mehr zu funktionieren. Nun also besser mit Leerzeichen trennen.

Dann sind folgende Inhalte in den Variablen:

$param1 = "Wert1"     # Vorbelegung des Parameterkopf
$param2 = 'test'      # aus der Parameterzeile gelesen
$param3 = $null       # Die variable gibt es nicht
$args.count = 2       # es sind ZWEI Parameter, da der Doppelpunkt hier ein Trenner ist
$args[0] = "-param3"  # Das ist der erste Teil der nicht aufgelösten Parameter
$args[1] = "wert3"    # Das ist der zweite Teil der nicht aufgelösten Parameter

Hinweis:
Verwenden Sie bitte nicht die Variable $host, um z.B. die IP-Adresse oder den Namen des Hosts zu übergeben, denn $host ist "readOnly"

Allerdings habe ich bei der Entwicklung von PRTG ExMetric ein paar komische Verhalten gesehen, die auch mit PowerShell zusammen hängen könnten.

Parameter Status Bemerkung

-switch

OK

Die einfache Übergabe eines Parameters als Switch funktioniert

-switch1 -switch2

OK

Das gleiche mit zwei Switches

-feld:wert

OK

Die einfache Übergabe eines Parameters mit einem Wert funktioniert

-feld:"wert1 wert2 wert3"

FAIL

Die Übergabe eines String mit mehreren Werten, die mit einem Leerzeichen getrennt waren, hat zumindest bei mir nicht funktioniert.

-feld:"wert1,wert2,wert3"

OK

Dafür konnte ich problemlos mit Komma als Trenner arbeiten

-feld:"wert1;wert2;wert3"

OK

Oder alternativ mit Semikolon

Ich habe nicht alle Varianten ausprobiert. Da ich meinem Sensor eine Liste von User, Servern o.ä. übergeben will und dabei sowohl Komma als auch Semikolon mir helfen, habe ich das nicht weiter verfolgt. Auf jeden Fall sollten sie Parameter, die sie übergeben, auch im Sensor nach der Auswertung entsprechende zur Fehlersuche ausgeben.

Hinweis:
Verwenden Sie nicht die "doppelten Anführungszeichen" sondern immer nur einfache und trennen Sie Arrays durch Komme oder Semikolon 

Platzhalter

Sie können in der Konfiguration des Sensors aber auch vordefinierte Variablen mit übergeben (Stand Nov 2013). Bei der Übergabe von Parametern mit "Anführungszeichen" müssen Sie aber einige Besonderheiten beachten. Ich möchte hier z.B. den Hostname des Device als Parameter URL an ein PowerShell-Skript übergeben

param (
   $url = "",
   $param2=""
)

In der Konfiguration des Device darf natürlich nur die IP-Adresse, der Hostname oder FQDN stehen. Ich hatte da auch schon mal "https://hostname" drin, so dass das Skript dann ein "http://http://hostname" verarbeitet hat.

Schreibweise Was kommt im Skript an Status
-url "http://192.168.178.1/status"

Funktioniert wie erwartet

OK

-url http://%host/status

Sie können problemlos den Platzhalter einfach einfügen. PRTG setzt ihn durch den Wert aus dem Device

OK

-url "http://%host/status"
-url 'http://%host/status'

Für einige Sonderfälle müssen Sie String in Anführungszeichen setzen. Auch hier ersetzt PRTG den Platzhalter. PRTG unterscheidet auch nicht nach der Art der Anführungszeichen

OK

-url "http://"%host"/status"

In der Schreibweise trennt PRGT den Parameter in mehrere Parameter auf. Der erste Parameter bekommt ein "http://" während der zweite Parameter dann ein "192.168.180.23/status" bekommt.

Fail

-url "http://""param2"

Beim Skript kommt hier ein Parameter mit dem Inhalt "http://"param2" an

Fail

-url 'http://\%host/status'

Der Versuch das "%" Zeichen per Escape-Prefix zu übergeben, lieferte aber nur ein "http://\192.168.180.23/status"

Fail

-url 'http://%%host/status'

Mit der Schreibweise kam dann ein "http://%192.168.180.23/status" im Skript an.

Fail

Es sieht so aus, als ob ein "%"-Zeichen nur übergeben wird, wenn es keinen passenden Parameter von PRTG gibt. Versuchen Sie also nicht ein "%host" als String in einen Parameter zu übergeben

Placeholder Description

%sensorid

ID des EXE/Script Sensor

%deviceid

ID des Geräts, auf dem der Sensor angelegt ist

%groupid

ID der Gruppe, in der der Sensor angelegt ist

%probeid

ID der Probe, unter der der Sensor angelegt wurde

%host

IP Adresse/DNS-Name des Devices, unter dem der Sensor angelegt ist

%device

Name des Devices, unter dem der Sensor angelegt ist

%group

Name der Gruppe in der das Device angelegt wurde

%probe

Name der Probe, unter der der Sensor angelegt wurde

%name oder %sensor

Name des EXE/Script Sensors

%windowsdomain

Windows Domäne der Anmeldedaten (kann vererbt sein)

%windowsUser

Windows Username der Anmeldedaten (kann vererbt sein)

%windowspassword

Windows Kennwort der Anmeldedaten (kann vererbt sein)

%linuxUser

Linux Username der Anmeldedaten (kann vererbt sein)

%linuxpassword

Linux Kennwort der Anmeldedaten (kann vererbt sein)

%snmpcommunity

SNMPV1 community string (kann vererbt sein)

Weitere Links

Hier die Links zu den API-Beschreibungen.