Tutorials

MQTT mit PowerShell unter Windows

MQTT aus PowerShell unter Windows: mosquitto_pub und mosquitto_sub in Pipelines, MQTTnet in pwsh geladen, TLS und geplante Aufgaben für Heartbeats und Checks.

Aktualisiert · 9 Min. Lesezeit

MQTT mit PowerShell unter Windows

PowerShell bringt keine MQTT-Cmdlets mit, aber es gibt zwei zuverlässige Wege, aus einem Windows-Skript mit einem Broker zu sprechen: die Programme mosquitto_pub / mosquitto_sub aufrufen und ihre Ausgabe als Pipeline behandeln oder die .NET-Bibliothek MQTTnet direkt in PowerShell 7 laden. Der erste Weg ist ideal für Einzeiler, Health Checks und geplante Aufgaben; der zweite gibt dir eine dauerhafte Verbindung und volle Kontrolle aus einer einzigen .ps1-Datei.

Dieser Guide behandelt beide – inklusive der zwei Fallen, in die fast jeder tappt: Anführungszeichen, die aus JSON-Payloads verschwinden, und Event-Handler, die mit „no Runspace available“ abstürzen. Alle Beispiele nutzen broker.connectmq.com; lass den Online-MQTT-Client offen, um die Nachrichten ankommen zu sehen.

Welcher Ansatz?

mosquitto-ClientsMQTTnet in PowerShell 7
InstallationMosquitto-Installer für WindowsEine DLL von NuGet
Läuft in Windows PowerShell 5.1JaNicht empfohlen
Dauerhafte VerbindungNein (ein Prozess pro Aufruf)Ja
Nachrichten empfangenstdout zeilenweise lesenQueue + Polling-Schleife
Ideal fürAlarme, Health Checks, schnelle TestsLang laufende Skripte, Tooling, Glue-Code

Wenn du am Ende mehr als eine Seite PowerShell rund um MQTTnet schreibst, ist eine kleine C#-Konsolen-App meist das bessere Werkzeug – siehe MQTT in C# mit MQTTnet.

Option 1: mosquitto_pub und mosquitto_sub

Lade den Windows-Installer von mosquitto.org herunter. Er installiert den Broker (den Dienst kannst du weglassen) und die Kommandozeilen-Clients nach C:\Program Files\mosquitto. Füge diesen Ordner zum PATH hinzu und teste die Verbindung:

@@CODE1@@

$LASTEXITCODE ist bei Erfolg 0 und ungleich null, wenn Verbindung oder Authentifizierung scheitern – mehr braucht ein Skript nicht. Ist TcpTestSucceeded False, liegt das Problem im Netzwerk und nicht bei MQTT – prüfe, ob der Port offen ist, und die Windows-Firewall. Willst du einen Broker auf derselben Maschine betreiben, erklärt MQTT-Broker unter Windows die Einrichtung als Dienst.

JSON senden, ohne die Anführungszeichen zu verlieren

Das ist der häufigste PowerShell-spezifische MQTT-Bug. In Windows PowerShell 5.1 und PowerShell 7.0–7.2 werden eingebettete doppelte Anführungszeichen entfernt, wenn Argumente an eine native .exe gehen – der Subscriber erhält dann {device:pc-01} statt gültigem JSON. PowerShell 7.3 hat die Argumentübergabe korrigiert, aber die robuste Lösung funktioniert überall: Baue das Objekt mit ConvertTo-Json und leite es per Pipe an mosquitto_pub -s weiter, das die Nachricht von der Standardeingabe liest.

@@CODE2@@

PowerShell hängt beim Pipen an ein natives Programm einen Zeilenumbruch an; JSON-Parser ignorieren ihn. Nutze -l statt -s, um jede Eingabezeile als eigene Nachricht zu senden.

Eingehende Nachrichten in einer Pipeline verarbeiten

mosquitto_sub -v gibt pro Zeile topic payload aus, und PowerShell macht aus jeder Zeile ein Pipeline-Objekt:

@@CODE3@@

Für einen Check, der auf genau eine Nachricht wartet, ergänze -C 1 -W 10: mosquitto_sub beendet sich nach der ersten Nachricht oder nach zehn Sekunden, bei Timeout mit einem Exit-Code ungleich null. Weitere Flags findest du in mosquitto_pub- und mosquitto_sub-Beispiele.

Option 2: MQTTnet in PowerShell 7

MQTTnet ist die meistgenutzte MQTT-Bibliothek für .NET. PowerShell 7 läuft auf modernem .NET und kann die DLL daher direkt laden. Lade ein 4.x-Paket von NuGet herunter und entpacke den netstandard2.0-Build:

@@CODE4@@

Verbinden und Publizieren funktioniert direkt aus PowerShell. Async-Methoden liefern Tasks; rufe .GetAwaiter().GetResult() auf, um auf sie zu warten (das zeigt außerdem die eigentliche Exception statt einer AggregateException):

@@CODE5@@

Das Method Chaining mit führendem Punkt erfordert PowerShell 7. Ein fehlgeschlagener Login wirft eine Exception wie Connecting with MQTT server failed (BadUserNameOrPassword). oder (NotAuthorized); das MQTT-Reason-Code-Nachschlagewerk erklärt jeden Wert.

Nachrichten empfangen ohne Runspace-Absturz

Der naheliegende Ansatz – $client.add_ApplicationMessageReceivedAsync({ ... }) – scheitert früher oder später mit:

There is no Runspace available to run scripts in this thread.

MQTTnet löst das Event auf einem .NET-Threadpool-Thread aus, und ein PowerShell-Scriptblock kann nur auf einem Thread mit Runspace laufen. Die saubere Lösung sind ein paar Zeilen C#, die jede Nachricht in eine threadsichere Queue legen; deine PowerShell-Schleife holt sie auf ihrem eigenen Thread ab.

@@CODE6@@

Der Timeout von 500 ms hält die Schleife für Strg+C ansprechbar, und der finally-Block sendet ein sauberes DISCONNECT, damit der Broker keinen Last Will auslöst. Add-Type kann einen Typ nur einmal pro Sitzung definieren; startest du das Skript zweimal in derselben Konsole, erhältst du Cannot add type. The type name 'MqttInbox' already exists. – öffne eine neue pwsh-Sitzung oder schütze den Aufruf mit if (-not ('MqttInbox' -as [type])).

Publiziere aus dem Online-Client auf testmqtt/ps/hello, und die Zeile sollte innerhalb einer Sekunde erscheinen.

Eine Nachricht an deinen PowerShell-Listener senden

TLS

Wechsle auf Port 8883 und aktiviere TLS im Options-Builder. MQTTnet prüft das Broker-Zertifikat gegen den Windows-Zertifikatspeicher, ein Broker mit öffentlichem Zertifikat braucht also nichts weiter:

@@CODE7@@

Ein geplanter Heartbeat

Alles zusammen: ein Skript, das den Maschinenstatus publiziert, und eine geplante Aufgabe, die es alle fünf Minuten ausführt.

@@CODE8@@

@@CODE9@@

--cafile zeigt auf eine PEM-Datei mit der CA, die das Zertifikat deines Brokers signiert hat. Fehler landen in einer Logdatei, und der Exit-Code ungleich null erscheint in der Aufgabenplanung als „Letztes Ausführungsergebnis“. Die obige Aufgabe läuft unter deinem Benutzer, solange du angemeldet bist – für unbeaufsichtigte Server registrierst du sie mit einem Dienstkonto und hinterlegst die Zugangsdaten als Umgebungsvariablen dieses Kontos oder mit dem SecretManagement-Modul. Abonniere testmqtt/ps/+/status, um jede Maschine melden zu sehen.

Fehlerbehebung

FehlerUrsacheLösung
mosquitto_pub : The term 'mosquitto_pub' is not recognizedInstallationsordner nicht im PATHC:\Program Files\mosquitto zum PATH hinzufügen
Error: Connection refusedFalscher Port oder der Broker hat die Verbindung abgelehntTest-NetConnection -Port; Port vs. TLS prüfen
Unable to find type [MQTTnet.MqttFactory]DLL nicht geladen oder eine 5.x-DLL mit anderen NamespacesZuerst Add-Type -Path ausführen; ein 4.x-Paket nutzen
Connecting with MQTT server failed (BadUserNameOrPassword).Falsche Zugangsdaten oder leere Umgebungsvariablen$env:MQTT_USER ausgeben; auf Tippfehler prüfen
There is no Runspace available to run scripts in this thread.Scriptblock als MQTTnet-Event-HandlerDie oben gezeigte C#-Queue verwenden
JSON kommt ohne Anführungszeichen anNative Argumentübergabe in PS 5.1 / 7.0–7.2Per Pipe an mosquitto_pub -s übergeben

PowerShell ist ein völlig brauchbarer MQTT-Client, sobald du seine Eigenheiten kennst: JSON über stdin schicken, $LASTEXITCODE prüfen und MQTTnet-Events auf der .NET-Seite einer Queue halten. Dieselbe Automatisierung unter Linux zeigt MQTT in Bash-Skripten.

Häufig gestellte Fragen

Kann PowerShell MQTT-Nachrichten ohne zusätzliche Software senden?

Nicht nativ – PowerShell hat keine MQTT-Cmdlets. Die zwei praktischen Optionen sind die Programme mosquitto_pub und mosquitto_sub aus dem Mosquitto-Installer für Windows oder die .NET-Bibliothek MQTTnet, die du mit Add-Type in PowerShell 7 lädst.

Warum bekomme ich "There is no Runspace available to run scripts in this thread"?

Du hast einen PowerShell-Scriptblock an ein MQTTnet-Event gehängt. MQTTnet löst Events auf .NET-Threadpool-Threads aus, die keinen PowerShell-Runspace haben, daher kann der Scriptblock nicht laufen. Stelle Nachrichten in einem kleinen C#-Helper in eine Queue und lies diese in deiner PowerShell-Schleife aus.

Warum kommt mein JSON in PowerShell ohne Anführungszeichen bei mosquitto_pub an?

Windows PowerShell 5.1 und PowerShell 7.0 bis 7.2 entfernen eingebettete doppelte Anführungszeichen, wenn sie Argumente an native Programme übergeben. Aktualisiere auf PowerShell 7.3 oder neuer oder leite das JSON per Pipe an mosquitto_pub -s weiter, damit es von der Standardeingabe gelesen wird.