Tutoriais

MQTT pelo PowerShell no Windows

Publique e assine MQTT pelo PowerShell no Windows: mosquitto_pub e mosquitto_sub em pipelines, MQTTnet carregado no pwsh, TLS e tarefas agendadas.

Atualizado · 9 min de leitura

MQTT pelo PowerShell no Windows

O PowerShell não tem cmdlets de MQTT embutidos, mas há duas formas confiáveis de falar com um broker a partir de um script no Windows: chamar os executáveis mosquitto_pub / mosquitto_sub e tratar a saída deles como um pipeline, ou carregar a biblioteca .NET MQTTnet direto no PowerShell 7. A primeira é perfeita para one-liners, health checks e tarefas agendadas; a segunda dá uma conexão persistente e controle total a partir de um único arquivo .ps1.

Este guia cobre as duas, incluindo as duas armadilhas que pegam quase todo mundo — aspas sumindo de payloads JSON e event handlers que quebram com "no Runspace available". Todos os exemplos usam broker.connectmq.com; deixe o cliente MQTT online aberto para ver as mensagens chegarem.

Qual abordagem?

Clientes mosquittoMQTTnet no PowerShell 7
InstalaçãoInstalador do Mosquitto para WindowsUma DLL do NuGet
Funciona no Windows PowerShell 5.1SimNão recomendado
Conexão persistenteNão (um processo por chamada)Sim
Recebimento de mensagensLer o stdout linha a linhaFila + loop de polling
Melhor paraAlertas, health checks, testes rápidosScripts de longa duração, ferramentas, código de integração

Se você acabar escrevendo mais de uma página de PowerShell em volta do MQTTnet, um pequeno app de console em C# costuma ser a ferramenta melhor — veja MQTT em C# com MQTTnet.

Opção 1: mosquitto_pub e mosquitto_sub

Baixe o instalador para Windows em mosquitto.org. Ele instala o broker (você pode pular o serviço) e os clientes de linha de comando em C:\Program Files\mosquitto. Adicione essa pasta ao PATH e teste a conexão:

@@CODE1@@

$LASTEXITCODE é 0 em caso de sucesso e diferente de zero quando a conexão ou a autenticação falha, que é tudo de que um script precisa. Se TcpTestSucceeded for False, o problema é a rede, não o MQTT — verifique se a porta está aberta e o firewall do Windows. Se quiser rodar um broker na mesma máquina, broker MQTT no Windows explica a configuração do serviço.

Enviando JSON sem perder as aspas

Este é o bug de MQTT mais comum e específico do PowerShell. No Windows PowerShell 5.1 e no PowerShell 7.0–7.2, aspas duplas internas são removidas quando argumentos são passados para um .exe nativo, então o subscriber recebe {device:pc-01} em vez de JSON válido. O PowerShell 7.3 corrigiu a passagem de argumentos, mas a solução robusta funciona em qualquer versão: monte o objeto com ConvertTo-Json e envie por pipe para mosquitto_pub -s, que lê a mensagem da entrada padrão.

@@CODE2@@

O PowerShell adiciona uma quebra de linha no final ao enviar por pipe para um programa nativo; parsers de JSON ignoram isso. Use -l em vez de -s para enviar cada linha de entrada como uma mensagem separada.

Processando mensagens recebidas em um pipeline

mosquitto_sub -v imprime topic payload por linha, e o PowerShell transforma cada linha em um objeto do pipeline:

@@CODE3@@

Para uma verificação que espera exatamente uma mensagem, adicione -C 1 -W 10: o mosquitto_sub encerra após a primeira mensagem ou após dez segundos, com código de saída diferente de zero em caso de timeout. Mais flags estão em exemplos de mosquitto_pub e mosquitto_sub.

Opção 2: MQTTnet dentro do PowerShell 7

O MQTTnet é a biblioteca MQTT para .NET mais usada. O PowerShell 7 roda sobre o .NET moderno, então consegue carregar a DLL diretamente. Baixe um pacote 4.x do NuGet e extraia o build netstandard2.0:

@@CODE4@@

Conectar e publicar funciona direto do PowerShell. Métodos async retornam tasks, então chame .GetAwaiter().GetResult() para esperar por eles (isso também mostra a exceção real em vez de uma AggregateException):

@@CODE5@@

O encadeamento de métodos com ponto no início da linha exige PowerShell 7. Um login com falha lança uma exceção como Connecting with MQTT server failed (BadUserNameOrPassword). ou (NotAuthorized); a consulta de reason codes MQTT explica cada valor.

Recebendo mensagens sem o erro de runspace

A abordagem óbvia — $client.add_ApplicationMessageReceivedAsync({ ... }) — falha cedo ou tarde com:

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

O MQTTnet dispara o evento em uma thread do thread pool do .NET, e um script block do PowerShell só roda em uma thread que tenha um runspace. A correção limpa são algumas linhas de C# que colocam cada mensagem em uma fila thread-safe; o seu loop do PowerShell as retira na própria thread.

@@CODE6@@

O timeout de 500 ms mantém o loop responsivo ao Ctrl+C, e o bloco finally envia um DISCONNECT limpo para que o broker não dispare um Last Will. O Add-Type só consegue definir um tipo uma vez por sessão; rodar o script duas vezes no mesmo console gera Cannot add type. The type name 'MqttInbox' already exists. — abra uma nova sessão pwsh ou proteja a chamada com if (-not ('MqttInbox' -as [type])).

Publique em testmqtt/ps/hello pelo cliente online e a linha deve aparecer em menos de um segundo.

Envie uma mensagem para o seu listener PowerShell

TLS

Mude para a porta 8883 e ative TLS no builder de opções. O MQTTnet valida o certificado do broker contra o repositório de certificados do Windows, então um broker com certificado público não precisa de mais nada:

@@CODE7@@

Um heartbeat agendado

Juntando as peças: um script que publica o status da máquina e uma tarefa agendada que o executa a cada cinco minutos.

@@CODE8@@

@@CODE9@@

--cafile aponta para um arquivo PEM com a CA que assinou o certificado do seu broker. Falhas vão para um arquivo de log, e o código de saída diferente de zero aparece como "Last Run Result" da tarefa no Agendador de Tarefas. A tarefa acima roda com o seu usuário enquanto você estiver logado — para servidores sem supervisão, registre-a com uma conta de serviço e guarde as credenciais como variáveis de ambiente dessa conta ou com o módulo SecretManagement. Assine testmqtt/ps/+/status para ver cada máquina se reportar.

Solução de problemas

ErroCausaCorreção
mosquitto_pub : The term 'mosquitto_pub' is not recognizedPasta de instalação fora do PATHAdicione C:\Program Files\mosquitto ao PATH
Error: Connection refusedPorta errada, ou o broker recusou a conexãoTest-NetConnection -Port; confira porta vs. TLS
Unable to find type [MQTTnet.MqttFactory]DLL não carregada, ou uma DLL 5.x com outros namespacesRode Add-Type -Path antes; use um pacote 4.x
Connecting with MQTT server failed (BadUserNameOrPassword).Credenciais erradas ou variáveis de ambiente vaziasImprima $env:MQTT_USER; procure erros de digitação
There is no Runspace available to run scripts in this thread.Script block usado como event handler do MQTTnetUse a fila em C# mostrada acima
O JSON chega sem aspasPassagem de argumentos nativos no PS 5.1 / 7.0–7.2Envie por pipe para mosquitto_pub -s

O PowerShell é um cliente MQTT perfeitamente válido quando você conhece suas manias: passe o JSON pelo stdin, verifique $LASTEXITCODE e mantenha os eventos do MQTTnet do lado .NET de uma fila. Para a mesma automação no Linux, veja MQTT em scripts Bash.

Perguntas frequentes

O PowerShell consegue publicar mensagens MQTT sem software extra?

Não de forma nativa — o PowerShell não tem cmdlets de MQTT. As duas opções práticas são os executáveis mosquitto_pub e mosquitto_sub do instalador do Mosquitto para Windows, ou carregar a biblioteca .NET MQTTnet no PowerShell 7 com Add-Type.

Por que recebo "There is no Runspace available to run scripts in this thread"?

Você associou um script block do PowerShell a um evento do MQTTnet. O MQTTnet dispara eventos em threads do thread pool do .NET que não têm runspace do PowerShell, então o script block não consegue rodar. Enfileire as mensagens em um pequeno helper em C# e leia a fila no seu loop do PowerShell.

Por que o mosquitto_pub recebe meu JSON sem aspas no PowerShell?

O Windows PowerShell 5.1 e o PowerShell 7.0 a 7.2 removem aspas duplas internas ao passar argumentos para programas nativos. Atualize para o PowerShell 7.3 ou mais recente, ou envie o JSON por pipe para mosquitto_pub -s, que lê da entrada padrão.