Para entender por que Start-Process e todos esses outros comandos são limitados, primeiro você precisa entender como um arquivo EXE típico funciona. Quando um arquivo EXE é executado, ele realiza qualquer ação para a qual foi projetado; ele envia um ping para algo (ping), inicia um instalador de software (setup), procura algum registro DNS (nslookup), seja o que for. Para esta parte e Start-Process a
nd outros comandos para iniciar um processo funcionam muito bem. É simples. A limitação ocorre quando esse EXE retorna alguma saída.
Podemos iniciar um processo no PowerShell de muitas maneiras diferentes. Temos os cmdlets Start-Process e Invoke-Expression
do PowerShell, podemos chamar o executável diretamente ou usar o símbolo de ampersand (&
) para invocar expressões. A maneira mais comum é usar Start-Process
porque é provavelmente a mais intuitiva. O PowerShell é conhecido por sua abordagem intuitiva para nomear comandos e Start-Process é uma excelente escolha. No entanto, esse comando é limitado.
Streams
Um arquivo EXE, como muitos outros arquivos executáveis não limitados ao Windows, tem o conceito de fluxos padrão. Fluxos padrão são como arquivos executáveis retornam saída. Esses fluxos vêm em três variantes; stdin, stdout e stderr. Stdin é o fluxo que pode ser passado para o executável, sobre o qual não vamos nos concentrar aqui. Stdout é o fluxo que o executável usa para enviar saída normal, não de erro.
Em termos do PowerShell, pense em stdout como o que Write-Output
retorna. Quando ocorre um erro (dependendo se o desenvolvedor do executável o escreveu corretamente), o executável deve retornar saída via stderr. Esta é uma corrente que é reservada para retornar qualquer informação de erro.
Essas correntes permitem que os usuários desses arquivos executáveis diferenciem entre o que é saída típica e o que é um erro. As correntes existem há décadas e, portanto, o Windows e o PowerShell sabem tudo sobre elas e adotaram as suas próprias.
Códigos de Saída
Um código de saída, código de retorno ou código de resultado é outro conceito antigo que os arquivos executáveis seguem também. Um código de saída é um número inteiro que permite ao executável sinalizar um status para o usuário quando ele sai.
Há alguns códigos de saída padrão que os programas são supostos a seguir, como se o código de saída for 0, tudo está bem, o código de saída 3010 significa que precisa de uma reinicialização e assim por diante. O PowerShell pode capturar este código de saída de algumas maneiras diferentes, como usando a variável automática $LastExitCode
. Os códigos de saída são mais um método que o arquivo executável comunica ao usuário.
Capturando Correntes e Códigos de Saída
Agora que você entende o que estamos trabalhando, vamos usar um exemplo. Para manter simples, vou usar o bom e velho ping.exe. Primeiro, vou pingar google.com, que retornará um resultado bem-sucedido. Não estamos usando o processo de inicialização do PowerShell aqui.
I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode
.
Você viu que o código de saída difere porque o resultado do ping foi diferente, mas você não viu fluxos porque nativamente o PowerShell não entende a diferença quando se trata de arquivos executáveis. O texto que você vê no console é branco; não o texto de erro vermelho que você conhece e ama.
Podemos capturar os fluxos e redirecionar para arquivos de algumas maneiras diferentes, como usando >
e 2>
como abaixo. Este é o método antigo.
Observe, no entanto, que, neste caso, mesmo que ping.exe esteja retornando um código de saída 1 (como mostrado acima), essa saída ainda vai para stdout. Isso é comum. Qual fluxo e código de saída são retornados depende completamente do desenvolvedor e vem em muitos estilos diferentes, infelizmente.
Se você quiser ir pelo caminho “novo”, poderia usar Start-Process
e usar os parâmetros -RedirectStandardError
e -RedirectStandardOutput
, mas eles ainda iriam apenas para arquivos.
Limitações do Start-Process
Você pode ver que iniciar um processo e retornar alguma saída comum não é muito comum. Além disso, o PowerShell não lida muito bem com os fluxos e códigos de saída. Se eu quisesse usar Start-process para executar ping.exe
e quisesse rastrear o que aconteceu no resultado, teria que fazer algo assim toda vez que quisesse executar um arquivo executável.
I still wouldn’t get my error text either!
Vamos corrigir tudo isso. Baixe uma pequena função que criei chamada Invoke-Process
da PowerShell Gallery.
Agora execute o ping usando um host válido e veja o que acontece.

Perceba como obtemos a mesma saída. Isso é bom!
Agora execute o comando ping usando um host inválido.

Agora observe que recebemos o típico texto de erro vermelho como esperado se algo deu errado. Invoke-Process
utiliza Start-Process
por baixo dos panos para capturar stdout, stderr e o código de saída, e então envia a saída para o fluxo correto. É assim que deve ser!
É uma pena que o PowerShell não facilite trabalhar com fluxos e códigos de saída de arquivos executáveis, mas suponho que hoje em dia, podemos adicionar isso agora que é de código aberto!