Ausführung der Runbooks
Wir haben drei unterschiedliche Möglichkeiten, die Runbooks auf unserem On-Prem-Server laufen zu lassen. Wir können das Runbook einerseits über Azure manuell triggern, andererseits auch Webhooks verwenden, um es an eigene Anwendungen anzubinden. Außerdem können wir den Automation Connector nutzen, um das Runbook aus einem PowerAutomate-Flow zu triggern.
Wir betrachten in diesem Beispiel nur das Azure Web UI und PowerAutomate.
Die Ausführung über das Web UI verläuft genauso wie zuvor, allerdings wird man nun gefragt, ob das Runbook in Azure oder in einer Hybrid Worker Group ausgeführt werden soll:

Hier wählen wir die von uns eben erstellte Gruppe aus und bestätigen die Ausführung. Nach einer kurzen Wartezeit erhalten wir die Ausgabe:

Diese stimmt mit der erwarteten Ausgabe überein, die wir bekommen haben, als wir den Computernamen direkt auf dem Server abgefragt haben:

Wir können nun also ein beliebiges PowerShell-Skript aus der Azure UI Remote auf unserem Server ausführen.
Parametrisierung des Skripts
Sehr häufig wird man ein parametrisiertes Skript ausführen wollen. Wenn man z.B. ein Skript verwendet, welches neue User im AD anlegen soll, benötigt man den Parameter für den Usernamen, der bei jeder Ausführung des Skripts übergeben werden muss. Die Parametrisierung erfolgt genauso wie bei einem herkömmlichen PowerShell-Skript. Wir ergänzen zur Demonstration unser Runbook um den String-Parameter „Name“:

Bei der Ausführung bekommen wir die Möglichkeit, einen Wert hierfür zu übergeben:

Die Ausgabe sieht dann wie erwartet aus:

Exception Handling
Es kann passieren, dass ein bestimmter PowerShell-Befehl eine Exception wirft. Dies passiert beispielsweise, wenn ein neuer AD-User angelegt werden soll dessen Username bereits existiert.
Um darauf reagieren zu können ist es wichtig zu verstehen, wie die Runbook-Jobs mit derartigen Fehlern umgehen.
Ein Runbook-Job, dessen Befehl einen Fehler hervorruft, hat am Ende trotzdem den Status „Completed“, da der Job an sich erfolgreich ausgeführt wurde. Der Status eines Jobs kann aber dennoch ein Indikator für mögliche Fehler sein. Hierfür müssen Anweisungen, die potenziell Fehler hervorrufen können, in try/catch Blöcke gepackt werden. Wir wollen das ganze an einem Beispiel betrachten, in dem wir ein AD-Computer-Objekt erzeugen:
New-AdComputer -Name $label -SAMAccountName $label -Path $OU
Sollte ein Objekt mit dem Namen bereits existieren, wirft der Befehl einen Fehler. Ohne try/catch würde ein Runbook-Job mit diesem Befehl trotzdem als „Completed“ markiert werden, auch wenn durch den Fehler kein Objekt erzeugt werden konnte.
Wenn wir aber stattdessen mit try/catch arbeiten, sieht es anders aus:
try{
New-AdComputer -Name $label -SAMAccountName $label -Path $OU -Enable $false
}
catch{
throw „error“
}
In diesem Fall ist der Status des Runbook-Jobs im Falle eines Fehlers bei der Ausführung „Failed“. So können wir auf einer höheren Ebene auf unerwartetes Verhalten in den Remote-Skripten reagieren. So auch z.B. in PowerAutomate.
Runbook aus einem PowerAutomate Flow triggern
Die Microsoft Power Platform verfügt über einen Automation Connector mit der Aktion „Auftrag Erstellen“, was so viel bedeutet wie „Job starten“. Bei der Verwendung sollten dennoch einige Dinge beachtet werden.

Die Einstellung „Auf Auftrag warten“ sollte auf „Ja“ gestellt werden, wenn sichergestellt werden muss, ob der Auftrag erfolgreich ausgeführt wurde. Die Ausführung eines Jobs benötigt Zeit und währenddessen verweilt der Job in dem Status „Queued“ oder „Running“. Wenn man also nicht auf den Job wartet, sondern direkt im nächsten Schritt den Status abfragt, wird man kein aussagekräftiges Ergebnis bekommen. Andererseits ist zu beachten, dass der Flow durch das Warten logischerweise extrem verlangsamt wird.
Im Hinblick auf die Zeit ist außerdem anzumerken, dass die Ausführung des Runbook-Jobs an sich ziemlich schnell ist. Der Trigger-Vorgang hingegen raubt verhältnismäßig viel Zeit, da ein Job erstellt, gequeued und dann erst ausgeführt werden muss. Es empfiehlt sich daher nach Möglichkeit lieber ein großes Runbook zu schreiben, welches einmal getriggert wird, als viele kleine Runbooks, die (ggf. auch parallel) aus dem Flow getriggert werden. Wenn die Ausführungsdauer auch nur ansatzweise ein Entscheidungskriterium ist, sollte die Modularität an dieser Stelle zu Gunsten der Zeit ausnahmsweise vernachlässigt werden. Eine Alternative wäre auch, einfach keine Antwort des Jobs abzuwarten. Dies ermöglicht die schnellste Flow-Ausführung, gibt aber keinerlei Feedback an einen PowerApps-User, der dann davon ausgeht, das der Vorgang ohne Probleme ausgeführt wurde.
Aus vielerlei Gründen ist es ebenfalls sinnvoll, den Flow im Falle eines Runbook-Job-Errors ebenfalls mit einem Fehler zu beenden.

Ein fertiger Flow kann dann ohne Probleme in einer PowerApp verwendet werden, wodurch wir nun ein beliebiges PowerShell Skript auf einem On-Prem-Server ausführen können.
Beiträge dieser Serie
- PowerApps nutzen, um PowerShell-Skripte remote auf lokalen On-Premises-Servern auszuführen | Teil 1
- PowerApps nutzen, um PowerShell-Skripte remote auf lokalen On-Premises-Servern auszuführen | Teil 2
- PowerApps nutzen, um PowerShell-Skripte remote auf lokalen On-Premises-Servern auszuführen | Teil 3
Lesetipp
Kennen Sie schon unsere Whitepaper? Laden Sie sich diese doch einfach zur Inspiration herunter:
Wenn Sie schon jetzt Ideen haben und nicht wissen, wo sie beginnen sollen: Unsere Microsoft 365-Experten unterstützen Sie gerne dabei, schon morgen mit Ihren smarten Lösungen zu beginnen. Wir freuen uns auf Ihren Anruf oder eine Nachricht über unser Kontaktformular.