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 mosquitto | MQTTnet no PowerShell 7 | |
|---|---|---|
| Instalação | Instalador do Mosquitto para Windows | Uma DLL do NuGet |
| Funciona no Windows PowerShell 5.1 | Sim | Não recomendado |
| Conexão persistente | Não (um processo por chamada) | Sim |
| Recebimento de mensagens | Ler o stdout linha a linha | Fila + loop de polling |
| Melhor para | Alertas, health checks, testes rápidos | Scripts 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
| Erro | Causa | Correção |
|---|---|---|
mosquitto_pub : The term 'mosquitto_pub' is not recognized | Pasta de instalação fora do PATH | Adicione C:\Program Files\mosquitto ao PATH |
Error: Connection refused | Porta errada, ou o broker recusou a conexão | Test-NetConnection -Port; confira porta vs. TLS |
Unable to find type [MQTTnet.MqttFactory] | DLL não carregada, ou uma DLL 5.x com outros namespaces | Rode Add-Type -Path antes; use um pacote 4.x |
Connecting with MQTT server failed (BadUserNameOrPassword). | Credenciais erradas ou variáveis de ambiente vazias | Imprima $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 MQTTnet | Use a fila em C# mostrada acima |
| O JSON chega sem aspas | Passagem de argumentos nativos no PS 5.1 / 7.0–7.2 | Envie 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.


