Tutoriels

MQTT depuis PowerShell sous Windows

Publiez et abonnez-vous en MQTT depuis PowerShell sous Windows : mosquitto_pub et mosquitto_sub en pipeline, MQTTnet chargé dans pwsh, TLS et tâches planifiées.

Mis à jour · 9 min de lecture

MQTT depuis PowerShell sous Windows

PowerShell n'a pas de cmdlets MQTT intégrées, mais il existe deux façons fiables de parler à un broker depuis un script Windows : appeler les exécutables mosquitto_pub / mosquitto_sub et traiter leur sortie comme un pipeline, ou charger la bibliothèque .NET MQTTnet directement dans PowerShell 7. La première est parfaite pour les one-liners, les health checks et les tâches planifiées ; la seconde vous donne une connexion persistante et un contrôle total depuis un seul fichier .ps1.

Ce guide couvre les deux, y compris les deux pièges dans lesquels presque tout le monde tombe : des guillemets qui disparaissent des payloads JSON et des event handlers qui plantent avec « no Runspace available ». Tous les exemples utilisent broker.connectmq.com ; gardez le client MQTT en ligne ouvert pour voir arriver les messages.

Quelle approche ?

Clients mosquittoMQTTnet dans PowerShell 7
InstallationInstalleur Mosquitto pour WindowsUne DLL depuis NuGet
Fonctionne dans Windows PowerShell 5.1OuiDéconseillé
Connexion persistanteNon (un processus par appel)Oui
Réception des messagesLire stdout ligne par ligneFile + boucle de polling
Idéal pourAlertes, health checks, tests rapidesScripts longue durée, outillage, code d'intégration

Si vous finissez par écrire plus d'une page de PowerShell autour de MQTTnet, une petite application console en C# est généralement un meilleur outil — voir MQTT en C# avec MQTTnet.

Option 1 : mosquitto_pub et mosquitto_sub

Téléchargez l'installeur Windows sur mosquitto.org. Il installe le broker (vous pouvez ignorer le service) et les clients en ligne de commande dans C:\Program Files\mosquitto. Ajoutez ce dossier à votre PATH et testez la connexion :

@@CODE1@@

$LASTEXITCODE vaut 0 en cas de succès et une valeur non nulle quand la connexion ou l'authentification échoue, ce qui suffit à un script. Si TcpTestSucceeded vaut False, le problème vient du réseau et non de MQTT — vérifiez si le port est ouvert et le pare-feu Windows. Pour faire tourner un broker sur la même machine, broker MQTT sous Windows explique la configuration du service.

Envoyer du JSON sans perdre les guillemets

C'est le bug MQTT le plus courant propre à PowerShell. Dans Windows PowerShell 5.1 et PowerShell 7.0–7.2, les guillemets doubles internes sont supprimés lors du passage d'arguments à un .exe natif : le subscriber reçoit {device:pc-01} au lieu d'un JSON valide. PowerShell 7.3 a corrigé le passage d'arguments, mais la solution robuste fonctionne partout : construisez l'objet avec ConvertTo-Json et envoyez-le par pipe à mosquitto_pub -s, qui lit le message sur l'entrée standard.

@@CODE2@@

PowerShell ajoute un saut de ligne final quand il envoie des données par pipe à un programme natif ; les parseurs JSON l'ignorent. Utilisez -l au lieu de -s pour envoyer chaque ligne d'entrée comme un message distinct.

Traiter les messages entrants dans un pipeline

mosquitto_sub -v affiche topic payload sur chaque ligne, et PowerShell transforme chaque ligne en objet du pipeline :

@@CODE3@@

Pour une vérification qui attend exactement un message, ajoutez -C 1 -W 10 : mosquitto_sub se termine après le premier message ou au bout de dix secondes, avec un code de sortie non nul en cas de timeout. D'autres options figurent dans exemples mosquitto_pub et mosquitto_sub.

Option 2 : MQTTnet dans PowerShell 7

MQTTnet est la bibliothèque MQTT .NET la plus utilisée. PowerShell 7 tourne sur le .NET moderne et peut donc charger la DLL directement. Téléchargez un package 4.x depuis NuGet et extrayez le build netstandard2.0 :

@@CODE4@@

La connexion et la publication fonctionnent directement depuis PowerShell. Les méthodes async renvoient des tasks : appelez .GetAwaiter().GetResult() pour les attendre (cela fait aussi remonter la vraie exception au lieu d'une AggregateException) :

@@CODE5@@

Le chaînage de méthodes avec un point en début de ligne nécessite PowerShell 7. Une connexion refusée lève une exception comme Connecting with MQTT server failed (BadUserNameOrPassword). ou (NotAuthorized) ; la recherche de reason codes MQTT explique chaque valeur.

Recevoir des messages sans le plantage du runspace

L'approche évidente — $client.add_ApplicationMessageReceivedAsync({ ... }) — échoue tôt ou tard avec :

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

MQTTnet déclenche l'événement sur un thread du thread pool .NET, et un script block PowerShell ne peut s'exécuter que sur un thread qui possède un runspace. La solution propre tient en quelques lignes de C# qui placent chaque message dans une file thread-safe ; votre boucle PowerShell les retire sur son propre thread.

@@CODE6@@

Le timeout de 500 ms garde la boucle réactive au Ctrl+C, et le bloc finally envoie un DISCONNECT propre pour que le broker ne déclenche pas de Last Will. Add-Type ne peut définir un type qu'une fois par session ; lancer le script deux fois dans la même console donne Cannot add type. The type name 'MqttInbox' already exists. — ouvrez une nouvelle session pwsh ou protégez l'appel avec if (-not ('MqttInbox' -as [type])).

Publiez sur testmqtt/ps/hello depuis le client en ligne : la ligne doit apparaître en moins d'une seconde.

Envoyer un message à votre listener PowerShell

TLS

Passez au port 8883 et activez TLS dans le builder d'options. MQTTnet valide le certificat du broker avec le magasin de certificats Windows, un broker doté d'un certificat public ne demande donc rien de plus :

@@CODE7@@

Un heartbeat planifié

En combinant les éléments : un script qui publie l'état de la machine et une tâche planifiée qui l'exécute toutes les cinq minutes.

@@CODE8@@

@@CODE9@@

--cafile pointe vers un fichier PEM contenant la CA qui a signé le certificat de votre broker. Les échecs sont écrits dans un fichier de log, et le code de sortie non nul apparaît comme « Résultat de la dernière exécution » dans le Planificateur de tâches. La tâche ci-dessus s'exécute sous votre compte tant que vous êtes connecté — pour des serveurs sans surveillance, enregistrez-la avec un compte de service et stockez les identifiants en variables d'environnement de ce compte ou avec le module SecretManagement. Abonnez-vous à testmqtt/ps/+/status pour voir chaque machine se signaler.

Dépannage

ErreurCauseCorrectif
mosquitto_pub : The term 'mosquitto_pub' is not recognizedDossier d'installation absent du PATHAjoutez C:\Program Files\mosquitto au PATH
Error: Connection refusedMauvais port, ou le broker a refusé la connexionTest-NetConnection -Port ; vérifiez port et TLS
Unable to find type [MQTTnet.MqttFactory]DLL non chargée, ou DLL 5.x avec d'autres namespacesExécutez d'abord Add-Type -Path ; utilisez un package 4.x
Connecting with MQTT server failed (BadUserNameOrPassword).Identifiants erronés ou variables d'environnement videsAffichez $env:MQTT_USER ; cherchez les fautes de frappe
There is no Runspace available to run scripts in this thread.Script block utilisé comme event handler MQTTnetUtilisez la file C# présentée plus haut
Le JSON arrive sans guillemetsPassage d'arguments natifs en PS 5.1 / 7.0–7.2Envoyez-le par pipe à mosquitto_pub -s

PowerShell est un client MQTT tout à fait valable une fois ses particularités connues : faites passer le JSON par stdin, vérifiez $LASTEXITCODE et laissez les événements MQTTnet du côté .NET d'une file. Pour la même automatisation sous Linux, voyez MQTT dans des scripts Bash.

Questions fréquentes

PowerShell peut-il publier des messages MQTT sans logiciel supplémentaire ?

Pas nativement — PowerShell n'a pas de cmdlets MQTT. Les deux options pratiques sont les exécutables mosquitto_pub et mosquitto_sub fournis par l'installeur Mosquitto pour Windows, ou le chargement de la bibliothèque .NET MQTTnet dans PowerShell 7 avec Add-Type.

Pourquoi ai-je l'erreur "There is no Runspace available to run scripts in this thread" ?

Vous avez attaché un script block PowerShell à un événement MQTTnet. MQTTnet déclenche ses événements sur des threads du thread pool .NET qui n'ont pas de runspace PowerShell, le script block ne peut donc pas s'exécuter. Mettez les messages en file dans un petit helper C# et lisez cette file depuis votre boucle PowerShell.

Pourquoi mosquitto_pub reçoit-il mon JSON sans guillemets dans PowerShell ?

Windows PowerShell 5.1 et PowerShell 7.0 à 7.2 suppriment les guillemets doubles internes lorsqu'ils passent des arguments à des programmes natifs. Passez à PowerShell 7.3 ou plus récent, ou envoyez le JSON par pipe à mosquitto_pub -s pour qu'il soit lu depuis l'entrée standard.