Per capire perché Start-Process e tutti questi altri comandi sono limitati, devi prima capire come funziona un tipico file EXE. Quando viene eseguito un file EXE, esegue l’azione per cui è stato progettato; fa il ping a qualcosa (ping), avvia un installer di software (setup), cerca un record DNS (nslookup), eccetera. Per questa parte e Start-Process a
e altri comandi per avviare un processo funzionano alla grande. È semplice. Il limite si presenta quando quel file EXE restituisce un output.
Possiamo avviare un processo in PowerShell in molti modi diversi. Abbiamo i cmdlet PowerShell Start-Process e Invoke-Expression
, possiamo chiamare direttamente l’eseguibile o usare l’ampersand (&
) per invocare espressioni. Il modo più comune è utilizzare Start-Process
perché è probabilmente il più intuitivo. PowerShell è noto per il suo approccio intuitivo alla denominazione dei comandi e Start-Process è una scelta eccellente. Tuttavia, quel comando è limitato.
Flussi
Un file EXE, come molti altri file eseguibili non limitati a Windows, ha il concetto di flussi standard. I flussi standard sono il modo in cui i file eseguibili restituiscono output. Questi flussi si presentano in tre varianti; stdin, stdout e stderr. Stdin è il flusso che può essere passato all’interno di l’eseguibile su cui non ci concentreremo qui. Stdout è il flusso che l’eseguibile utilizza per inviare output normale non di errore.
In termini di PowerShell, pensa a stdout come a ciò che restituisce Write-Output
. Quando si verifica un errore (a seconda se lo sviluppatore dell’eseguibile l’ha scritto correttamente), l’eseguibile dovrebbe restituire l’output tramite stderr. Questo è uno stream che viene riservato per restituire eventuali informazioni sugli errori.
Questi stream permettono agli utenti di questi file eseguibili di differenziare tra l’output tipico e ciò che è un errore. Gli stream esistono da decenni e Windows, quindi PowerShell, ne sa tutto e ha adottato il proprio.
Codici di Uscita
Un codice di uscita, codice di ritorno o codice di risultato è un altro concetto vecchio come il mondo che i file eseguibili seguono. Un codice di uscita è un numero intero che consente all’eseguibile di segnalare uno stato all’utente quando esce.
Ci sono alcuni codici di uscita standard che i programmi dovrebbero seguire, come ad esempio se il codice di uscita è 0, tutto va bene, il codice di uscita 3010 significa che è necessario riavviare e così via. PowerShell può catturare questo codice di uscita in diversi modi, ad esempio utilizzando la variabile automatica $LastExitCode
. I codici di uscita sono un altro metodo con cui il file eseguibile comunica all’utente.
Cattura di Stream e Codici di Uscita
Ora che hai capito con cosa stiamo lavorando, usiamo un esempio. Per mantenerlo semplice, userò il vecchio ping.exe. Prima, farò un ping a google.com che restituirà un risultato di successo. Non stiamo utilizzando qui il processo di avvio di PowerShell.
I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode
.
Hai visto che il codice di uscita differisce perché il risultato di ping era diverso, ma non hai visto i flussi perché nativamente PowerShell non comprende la differenza quando si tratta di file eseguibili. Il testo che vedi nella console è bianco; non il testo di errore rosso che conosci e ami.
Possiamo catturare i flussi e ridirigerli su file in diversi modi, come utilizzando >
e 2>
come mostrato di seguito. Questo è il modo vecchio stile.
Notate però che, in questo caso, anche se ping.exe restituisce un codice di uscita pari a 1 (come mostrato sopra), quell’output va comunque a stdout. Questo è comune. A quale flusso e codice di uscita viene restituito è completamente a discrezione dello sviluppatore e viene in molti stili diversi, sfortunatamente.
Se vuoi procedere nel modo “nuova scuola” potresti utilizzare Start-Process
e utilizzare i parametri -RedirectStandardError
e -RedirectStandardOutput
, ma andrebbero comunque solo su file.
Limitazioni di Start-Process
Puoi vedere che avviare un processo e restituire qualche output comune non è troppo comune. Inoltre, PowerShell non gestisce molto bene i flussi e i codici di uscita. Se dovessi utilizzare Start-process per eseguire ping.exe
e volessi tracciare cosa è successo nel risultato, dovrei fare qualcosa del genere ogni volta che volessi eseguire un file eseguibile.
I still wouldn’t get my error text either!
Correggiamo tutto questo. Scarica una piccola funzione che ho creato chiamata Invoke-Process
dalla PowerShell Gallery.
Ora esegui ping utilizzando un host valido e vedi cosa succede.

Osserva come otteniamo lo stesso output. Questo è buono!
Ora esegui il ping utilizzando un host non valido.

Ora notiamo che otteniamo il tipico testo di errore rosso come ci si aspetterebbe se qualcosa fosse andato storto. Invoke-Process
utilizza Start-Process
sotto il cofano per catturare stdout, stderr e il codice di uscita e quindi invia l’output allo stream a cui dovrebbe andare. È così che dovrebbe essere!
Peccato che PowerShell non abbia reso più facile lavorare con gli stream e i codici di uscita dai file eseguibili, ma suppongo che oggi, ora che è open source, possiamo aggiungerlo lì dentro!