Externe Programme in PowerShell ausführen, Exit-Code abfragen


    Tags:

    Powershell-LogoDie zahlreichen Module für Power­Shell decken mit ihren Cmdlets die meisten Kompo­nenten der Microsoft-Plattform ab. Dennoch benötigt man gele­gent­lich die alten Programme für die Kommando­­zeile. PowerShell bietet mehrere Optionen, diese auszu­führen und um deren Rückgabe­wert 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.

    Beim Befehl 'fc' erhält das Alias den Vorzug über das externe Programm. Dieses startet man über den vollen Namen.

    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 Sicherheits­grü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.

    PowerShell startet Programme ohne Pfadangabe nicht aus dem aktuellen Verzeichnis.

    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 Eingabeauf­forderung setzt man den Aufruf einfach in Anführungsz­eichen, 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 Standard­verhalten für bloße Strings. Um PowerShell mitzuteilen, dass es sich dabei um einen Programm­aufruf handelt, stellt man der Zeichenkette den Call-Operator '&' voran:

    & "C:\Program Files\Tools\7-Zip\7zFM.exe"

    Der Aufruf des Programms in Anführungszeichen gibt diesen bloß wieder als String aus.

    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.

    7-Zip gibt 2 zurück, wenn es ein Archiv nicht findet. $? zeigt in diesem Fall nur False, $LASTEXITCODE den tatsächlichen Wert.

    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

    Wir ver­wenden Ihre Mail-Adresse nur für den Ver­sand der News­letter.
    Es erfolgt keine per­sonen­be­zogene Auswertung.

    Bild von Wolfgang Sommergut
    Wolfgang Sommergut hat lang­jährige Erfahrung als Fach­autor, Berater und Kon­ferenz­sprecher zu ver­schie­denen Themen der IT. Da­ne­ben war er als System­ad­mi­ni­stra­tor und Con­sultant tätig.
    // Kontakt: E-Mail, XING, LinkedIn //

    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.

    Bild von Wolfgang Sommergut

    Ich bin in Zusammenhang mit winget darauf gestoßen :-)