Tags: PowerShell
Die zahlreichen Module für PowerShell decken mit ihren Cmdlets die meisten Komponenten der Microsoft-Plattform ab. Dennoch benötigt man gelegentlich die alten Programme für die Kommandozeile. PowerShell bietet mehrere Optionen, diese auszuführen und um deren Rückgabewert abzufragen.
Grundsätzlich muss man nur den Namen eines Programms auf der Kommandozeile von PowerShell eingeben, um dieses zu starten. Dies klappt in der Regel problemlos mit den integrierten Tools, die in Verzeichnissen %SystemRoot% und %SystemRoot%\system32 liegen.
Priorität von Kommandos
Ruft man aber beispielsweise fc auf, um zwei Dateien zu vergleichen, dann wird man ein unerwartetes Ergebnis erhalten. Der Grund besteht darin, dass PowerShell standardmäßig ein Alias gleichen Namens für Format-Custom enthält. Dieses kommt vor einem externen Programm zum Zug.
Bei der Ausführung von Kommandos gilt folgende Priorität:
- Alias
- Function
- Cmdlet
- Externe Programme sowie Nicht-PowerShell-Scripts
Die Lösung für Programme, die sich im Suchpfad befinden, besteht also darin, dass man sie samt Dateiendung aufruft, also zum Beispiel fc.exe.
Programme aus dem aktuellen Verzeichnis starten
Eine weitere Eigenheit zeigt PowerShell, wenn man Programme aus dem aktuellen Verzeichnis starten möchte und sich dieses nicht im Suchpfad befindet. Dann verhält es sich so wie von den Unix-Shells bekannt und führt es aus Sicherheitsgründen nicht aus, wenn man bloß dessen Namen eingibt.
Man erhält neben der Fehlermeldung auch einen Hinweis, dass das Programm am aktuellen Ort vorhanden sei.
Man muss es in diesem Fall um den relativen oder absoluten Pfad ergänzen, zum Beispiel
.\blat.exe
Leerzeichen im Pfad
Eine weitere Hürde taucht auf, wenn man ein Programm starten möchte, dessen Name oder Pfad ein Leerzeichen enthält. In der alten Eingabeaufforderung setzt man den Aufruf einfach in Anführungszeichen, um eine Fehlermeldung zu verhindern. Tut man das Gleiche in PowerShell, indem man etwa
"C:\Program Files\Tools\7-Zip\7zFM.exe"
eingibt, dann erscheint der Befehl einfach als Ausgabe auf der Kommandozeile. Echo ist nämlich das Standardverhalten für bloße Strings. Um PowerShell mitzuteilen, dass es sich dabei um einen Programmaufruf handelt, stellt man der Zeichenkette den Call-Operator '&' voran:
& "C:\Program Files\Tools\7-Zip\7zFM.exe"
Zu beachten ist dabei, dass eventuelle Argumente nicht innerhalb der Anführungszeichen stehen sollen:
& 'C:\Program Files\Tools\7-Zip\7z.exe' l .\archive.zip
Grundsätzlich ist es auch möglich, den Aufruf in einer Variablen zu speichern, etwa wenn man ihn dynamisch generieren möchte. Diese übergibt man dann dem Call-Operator:
$c = "C:\Program Files\Tools\7-Zip\7zFM.exe"
& $c
Rückgabewert ermitteln
In Scripts möchte man den weiteren Ablauf oft davon abhängig machen, ob ein Befehl erfolgreich ausgeführt werden konnte. PowerShell bietet für Cmdlets ein ausgewachsenes Error-Handling mit try/catch/finally. Dieses lässt sich auf Win32-Programme nur über Umwege anwenden.
Native Applikationen liefern zumeist einen Rückgabewert, aus dem hervorgeht, wie seine Ausführung verlaufen ist. Dabei geht es nicht nur um Erfolg oder Misserfolg, vielmehr kann ein Programm auch mit bestimmten Werten diverse aufgetretene Ereignisse abbilden.
Traditionell steht der Wert 0 für erfolgreiche Ausführung, aber es bleibt dem Entwickler der Software überlassen, welche Exit-Codes er für welchen Abschluss des Programms vorsieht.
Möchte man nur wissen, ob die Ausführung eines Programms gelungen oder gescheitert ist, dann kann man dies der automatischen Variablen $? entnehmen. Sie nimmt immer nur die Werte true oder false an.
Das PowerShell-Gegenstück zu ERRORLEVEL in cmd.exe ist $LASTEXITCODE. Über diese Variable erfährt man den nummerischen Exit-Code des Programms und kann ihn etwa in einem switch-Block oder einem if-Statement auswerten.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
Weitere Links
2 Kommentare
Der gute alte Exit Code :-) Interessant. Witzigerweise bisher nie in PS verwendet oder den Bedarf gehabt. Trotzdem Danke.
Ich bin in Zusammenhang mit winget darauf gestoßen :-)