Para entender por qué Start-Process y todos estos otros comandos están limitados, primero debes entender cómo funciona un archivo EXE típico. Cuando se ejecuta un archivo EXE, realiza la acción para la cual fue diseñado; hace ping a algo (ping), inicia un instalador de software (setup), busca algún registro DNS (nslookup), lo que sea. Para esta parte y Start-Process y
otros comandos para iniciar un proceso funcionan muy bien. Es simple. La limitación ocurre cuando ese EXE devuelve alguna salida.
Podemos iniciar un proceso en PowerShell de muchas formas diferentes. Tenemos los cmdlets PowerShell Start-Process e Invoke-Expression
, podemos llamar directamente al ejecutable o usar el ampersand (&
) para invocar expresiones. La forma más común es usar Start-Process
porque probablemente es la más intuitiva. PowerShell es conocido por su enfoque intuitivo en la nomenclatura de comandos y Start-Process es una excelente opción. Sin embargo, ese comando está limitado.
Flujos
Un archivo EXE, al igual que muchos otros archivos ejecutables no limitados a Windows, tiene un concepto de flujos estándar. Los flujos estándar son la forma en que los archivos ejecutables devuelven la salida. Estos flujos vienen en tres variantes: stdin, stdout y stderr. Stdin es el flujo que puede pasar al ejecutable, en lo que no nos enfocaremos aquí. Stdout es el flujo que el ejecutable utiliza para enviar salida normal sin errores.
En términos de PowerShell, piensa en stdout como lo que devuelve Write-Output
. Cuando ocurre un error (dependiendo de si el desarrollador del ejecutable lo escribió correctamente), el ejecutable debería devolver la salida a través de stderr. Este es un flujo que se reserva para devolver cualquier información de error.
Estos flujos permiten a los usuarios de estos archivos ejecutables diferenciar entre lo que es una salida típica y lo que es un error. Los flujos han existido durante décadas y Windows, por lo tanto, PowerShell sabe todo sobre ellos y han adoptado los suyos propios.
Códigos de salida
Un código de salida, código de retorno o código de resultado es otro concepto antiguo que siguen los archivos ejecutables. Un código de salida es un entero que permite al ejecutable señalar un estado al usuario cuando sale.
Hay algunos códigos de salida estándar que se supone que los programas siguen, como si el código de salida es 0, todo está bien, el código de salida 3010 significa que necesita un reinicio, y así sucesivamente. PowerShell puede capturar este código de salida de varias maneras, como usar la variable automática $LastExitCode
. Los códigos de salida son otro método mediante el cual el archivo ejecutable se comunica con el usuario.
Capturando Flujos y Códigos de Salida
Ahora que entiendes con qué estamos trabajando, usemos un ejemplo. Para mantenerlo simple, usaré el buen viejo ping.exe. Primero, haré ping a google.com, lo que devolverá un resultado exitoso. No estamos usando PowerShell para iniciar el proceso aquí.
I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode
.
Viste que el código de salida difiere porque el resultado del ping fue diferente, pero no viste flujos porque nativamente PowerShell no entiende la diferencia cuando se trata de archivos ejecutables. El texto que ves en la consola es blanco; no es el texto de error rojo que conoces y amas.
Podemos capturar los flujos y redirigirlos a archivos de algunas formas diferentes, como usar >
y 2>
como se muestra a continuación. Esta es la forma antigua.
Observa, sin embargo, que, en este caso, aunque ping.exe está devolviendo un código de salida de 1 (como se muestra arriba), esa salida aún va a stdout. Esto es común. El flujo y el código de salida que se devuelven dependen completamente del desarrollador y vienen en muchos estilos diferentes, desafortunadamente.
Si prefieres ir por la “nueva escuela”, podrías usar Start-Process
y usar los parámetros -RedirectStandardError
y -RedirectStandardOutput
, pero aún así solo irían a archivos.
Limitaciones de Start-Process
Puedes ver que iniciar un proceso y devolver alguna salida común no es demasiado común. Además, PowerShell no maneja muy bien los flujos y los códigos de salida. Si quisiera usar Start-process para ejecutar ping.exe
y quisiera rastrear lo que sucedió en el resultado, tendría que hacer algo como esto cada vez que quisiera ejecutar un archivo ejecutable.
I still wouldn’t get my error text either!
Arreglemos todo esto. Descarga una pequeña función que creé llamada Invoke-Process
desde la PowerShell Gallery.
Ahora ejecuta ping usando un host válido y mira qué sucede.

Observa cómo obtenemos la misma salida. ¡Esto es bueno!
Ahora ejecuta ping usando un host no válido.

Ahora observa que obtenemos el típico texto de error rojo como esperaríamos si algo saliera mal. Invoke-Process
utiliza Start-Process
bajo la superficie para capturar stdout, stderr y el código de salida, y luego envía la salida a cualquier flujo al que se supone que debe ir. ¡Así es como debería ser!
Lástima que PowerShell no lo hizo más fácil trabajar con flujos y códigos de salida de archivos ejecutables, pero supongo que hoy en día, podemos agregar eso ahora que es de código abierto.