Om te begrijpen waarom Start-Process en al deze andere opdrachten beperkt zijn, moet je eerst begrijpen hoe een typisch EXE-bestand werkt. Wanneer een EXE-bestand wordt uitgevoerd, voert het de actie uit waarvoor het is ontworpen; het pingt iets (ping), start een software-installatieprogramma (setup), zoekt naar een DNS-record (nslookup), wat dan ook. Voor dit deel en Start-Process en
andere opdrachten om een proces te starten werkt geweldig. Het is eenvoudig. De beperking komt wanneer dat EXE-bestand enige uitvoer retourneert.
We kunnen een proces starten in PowerShell op veel verschillende manieren. We hebben de PowerShell Start-Process en Invoke-Expression
cmdlets, we kunnen het uitvoerbare bestand rechtstreeks aanroepen of de ampersand (&
) gebruiken om expressies aan te roepen. De meest gebruikelijke manier is om Start-Process
te gebruiken omdat het waarschijnlijk het meest intuïtief is. PowerShell staat bekend om zijn intuïtieve benadering van het benoemen van commando’s en Start-Process is een uitstekende keuze. Echter, die opdracht heeft beperkingen.
Streams
Een EXE-bestand, net als veel andere uitvoerbare bestanden, niet beperkt tot Windows, heeft een concept van standaardstreams. Standaardstreams zijn hoe uitvoerbare bestanden uitvoer retourneren. Deze streams komen in drie smaken; stdin, stdout en stderr. Stdin is de stream die naar het uitvoerbare bestand kan worden doorgegeven, waar we hier niet op zullen focussen. Stdout is de stream die het uitvoerbare bestand gebruikt om normale niet-foutuitvoer te verzenden.
In PowerShell-termen kun je stdout beschouwen als wat Write-Output
retourneert. Wanneer er een fout optreedt (afhankelijk van of de ontwikkelaar van het uitvoerbare bestand het correct heeft geschreven), zou het uitvoerbare bestand output moeten retourneren via stderr. Dit is een stream die apart is gezet voor het retourneren van foutinformatie.
Deze streams stellen gebruikers van deze uitvoerbare bestanden in staat om onderscheid te maken tussen wat gebruikelijke output is en wat een fout is. Streams bestaan al tientallen jaren, en Windows en dus PowerShell weten er alles van en hebben er zelfs hun eigen versie van aangenomen.
Exit-codes
Een exit-code, retourcode of resultaatcode is nog een oud concept dat uitvoerbare bestanden ook volgen. Een exit-code is een geheel getal dat het het uitvoerbare bestand mogelijk maakt om bij het afsluiten een status aan de gebruiker door te geven.
Er zijn enkele standaard exit-codes die programma’s zouden moeten volgen, zoals als de exit-code 0 is, is alles in orde, exit-code 3010 betekent dat er een herstart nodig is, enzovoort. PowerShell kan deze exit-code op verschillende manieren vastleggen, zoals het gebruik van de automatische variabele $LastExitCode
. Exit-codes zijn nog een manier waarop het uitvoerbare bestand communiceert met de gebruiker.
Streams en Exit-codes Vastleggen
Nu je begrijpt waarmee we werken, laten we een voorbeeld gebruiken. Om het eenvoudig te houden, zal ik de goede oude ping.exe gebruiken. Eerst zal ik pingen naar google.com, wat een succesvol resultaat zou moeten opleveren. We gebruiken hier niet PowerShell Start-Process.
I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode
.
Je zag dat de exit-code verschilt omdat het resultaat van ping anders was, maar je zag geen streams omdat PowerShell van nature het verschil niet begrijpt als het gaat om uitvoerbare bestanden. De tekst die je ziet in de console is wit; niet de rode fouttekst waar je van houdt.
We kunnen de streams vastleggen en omleiden naar bestanden op verschillende manieren, zoals het gebruik van >
en 2>
zoals hieronder. Dit is de ouderwetse manier.
Merk echter op dat, in dit geval, zelfs als ping.exe een exit-code van 1 retourneert (zoals hierboven getoond), die uitvoer nog steeds naar stdout gaat. Dit is gebruikelijk. Welke stream en exitcode worden geretourneerd, is volledig aan de ontwikkelaar en komt in veel verschillende stijlen voor, helaas.
Als je de “nieuwe school” wilt volgen, kun je Start-Process
gebruiken en de parameters -RedirectStandardError
en -RedirectStandardOutput
gebruiken, maar ze worden nog steeds alleen naar bestanden geleid.
Beperkingen van Start-Process
Je kunt zien dat het starten van een proces en het retourneren van enkele algemene uitvoer niet al te gebruikelijk is. Bovendien behandelt PowerShell de streams en exitcodes niet al te goed. Als ik Start-Process zou gebruiken om ping.exe
uit te voeren en wilde bijhouden wat er in het resultaat gebeurde, zou ik iets als dit moeten doen elke keer dat ik een uitvoerbaar bestand wilde uitvoeren.
I still wouldn’t get my error text either!
Laten we dit allemaal oplossen. Download een kleine functie die ik heb gemaakt genaamd Invoke-Process
van de PowerShell Gallery.
Voer nu ping uit met behulp van een geldige host en kijk wat er gebeurt.

Merk op hoe we dezelfde uitvoer krijgen. Dat is goed!
Voer nu ping uit met gebruik van een ongeldige host.

Let nu op dat we de typische rode fouttekst krijgen zoals we zouden verwachten als er iets mis ging. Invoke-Process
gebruikt Start-Process
onderliggend om stdout, stderr en de exitcode vast te leggen, en stuurt vervolgens de uitvoer naar de juiste stream. Zo hoort het te zijn!
Het is jammer dat PowerShell het niet eenvoudiger heeft gemaakt om met streams en exitcodes van uitvoerbare bestanden te werken, maar ik veronderstel dat we dat tegenwoordig kunnen toevoegen nu het open source is!