Welche internen Befehle von cmd.exe löschen den ERRORLEVEL bei Erfolg auf 0?

Eine häufige Methode zur Behandlung von Fehlern in Windows-Batchskripts ist die Verwendung von Dingen wie
if errorlevel 1 ... oder if %errorlevel% neq 0 ... Oftmals möchte man, dass der Fehlerbehandlungscode das ERRORLEVEL erhält.

Ich glaube, dass alle externen Befehle immer dazu führen, dass ERRORLEVEL auf einen Wert gesetzt wird, so dass der Fehlerbehandlungscode den ERRORLEVEL in einer Umgebungsvariablen vor dem Ausführen eines externen Befehls beibehalten muss.

Aber was ist mit internen Befehlen? Das Problem ist, dass einige interne Befehle das ERRORLEVEL auf 0 setzen, wenn sie erfolgreich sind, und andere nicht. Und ich kann keine Dokumentation finden, die angibt, welche Befehle was tun.

Die Frage ist also, welche internen Befehle den ERRORLEVEL bei Erfolg auf 0 setzen. Dies ist keine allgemeine Frage zu zurückgegebenen ERRORLEVEL-Codes, sondern ausschließlich zu Erfolgsergebnissen.

Es gibt Beiträge wie Was ist der einfachste Weg, um ERRORLEVEL auf Null zurückzusetzen? und Windows-Batchdateien: .bat vs .cmd? das gibt teilweise Antworten. Aber ich habe noch nie eine umfassende Liste gesehen.

Hinweis: Ich bin seit Jahren neugierig darauf. Also entschied ich mich endlich, eine Reihe von Experimenten durchzuführen und eine definitive Antwort zu finden. Ich poste diese Frage und teile mit, was ich gefunden habe.

    Diese Antwort basiert auf Experimenten, die ich unter Windows 10 ausgeführt habe. Ich bezweifle, dass es Unterschiede zu früheren Windows-Versionen gibt, die cmd.exe verwenden, aber es ist möglich.

    Beachten Sie auch – Diese Antwort versucht nicht, das ERRORLEVEL-Ergebnis zu dokumentieren, wenn ein interner Befehl einen Fehler feststellt (mit Ausnahme eines kleinen Bits, der DEL und ERASE betrifft).

    Es gibt nicht nur einen Unterschied zwischen Befehlen, sondern ein einzelner Befehl kann sich je nachdem, ob er von der Befehlszeile aus ausgeführt wurde, in einem Stapelscript mit der Erweiterung .bat oder in einem Stapelscript mit der Erweiterung .cmd verhalten.

    Die folgende Befehlsgruppe löscht den ERRORLEVEL bei Erfolg niemals auf 0, unabhängig vom Kontext, sondern bewahrt stattdessen den vorherigen ERRORLEVEL:

    • UNTERBRECHUNG
    • CLS
    • ECHO
    • ENDLOCAL
    • FOR: Offensichtlich können Befehle in der DO-Klausel das ERRORLEVEL setzen, aber ein erfolgreiches FOR mit mindestens einer Iteration setzt das ERRORLEVEL nicht allein auf 0.
    • GEHE ZU
    • IF: Offensichtlich können die von IF ausgeführten Befehle den ERRORLEVEL setzen, aber ein erfolgreicher IF setzt ERRORLEVEL nicht selbst auf 0.
    • SCHLÜSSEL
    • PAUSE
    • POPD
    • RD
    • REM
    • RMDIR
    • VERSCHIEBUNG
    • ANFANG
    • TITEL

    Der nächste Satz von Befehlen löscht den ERRORLEVEL immer bei Erfolg, unabhängig vom Kontext:

    • CD
    • CHDIR
    • FARBE
    • KOPIEREN
    • DATUM
    • DEL: Löscht ERRORLEVEL immer, selbst wenn DEL fehlschlägt (außer wenn es ohne ein Dateiargument ausgeführt wird ) .
    • DIR
    • ERASE: Löscht ERRORLEVEL immer, auch wenn ERASE fehlschlägt. (außer wenn ohne Dateiargument ausgeführt wird) .
    • MD
    • MKDIR
    • MKLINK
    • BEWEGUNG
    • PUSHD
    • REN
    • UMBENENNEN
    • SETLOCAL
    • ZEIT
    • ART
    • VER
    • ÜBERPRÜFEN
    • VOL

    Dann gibt es diese Befehle, die ERRORLEVEL bei Erfolg nicht löschen, wenn sie von der Befehlszeile oder innerhalb eines Skripts mit einer Erweiterung von .bat ausgegeben werden, aber das ERRORLEVEL auf 0 löschen, wenn es von einem Skript mit einer Erweiterung von .cmd ausgegeben wird. Weitere Informationen finden Sie unter https://stackoverflow.com/a/148991/1012053 und https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J .

    • ASSOC
    • DPATH
    • FTYPE
    • PFAD
    • PROMPT
    • EINSTELLEN

    Schließlich gibt es diese Befehle, die nicht in eine der vorherigen Kategorien passen:

    • CALL: Wenn ein: routine- oder Batch-Script CALLed ist, wird ERRORLEVEL ausschließlich vom CALLed-Skript oder: routine gesteuert. Aber jeder andere Typ von erfolgreichem CALL zu einem Befehl wird ERRORLEVEL immer auf 0 löschen, wenn der CALLed-Befehl es nicht anders setzt.
      Beispiel: call echo OK .

    • BEENDEN: Wenn ohne /B , wird die cmd.exe-Sitzung beendet und es gibt keinen ERRORLEVEL mehr, nur den Rückkehrcode cmd.exe. Offensichtlich löscht EXIT /B 0 das ERRORLEVEL auf 0, aber EXIT /B ohne einen Wert behält das vorherige ERRORLEVEL bei.

    Ich glaube, dass alle internen Befehle berücksichtigt werden, es sei denn, es gibt einen undokumentierten Befehl, den ich verpasst habe.

    Ihre Beschreibung des Befehls CALL ist unvollständig:

    CALL: Löscht ERRORLEVEL, wenn der Befehl CALLed es nicht anders setzt. Beispiel: call echo OK .

    Überprüfen Sie dieses kleine Beispiel:

     @echo off call :setTwo echo Set two: %errorlevel% call :preserve echo Preserve: %errorlevel% call echo Reset echo Reset: %errorlevel% call :subNotExists 2> NUL echo Sub not exist: %errorlevel% goto :EOF :setTwo exit /B 2 :preserve echo Preserve exit /B 

    Ausgabe:

     Set two: 2 Preserve Preserve: 2 Reset Reset: 0 Sub not exist: 1 

    CALL Beschreibung sollte etwa so lauten:

    • CALL: Löscht ERRORLEVEL, wenn der Befehl CALLed es nicht anders setzt. Beispiel: call echo OK , aber wenn der aufgerufene Befehl ein Unterprogramm ist, behält es das vorherige ERRORLEVEL bei. Wenn die aufgerufene Subroutine nicht existiert, wird ERRORLEVEL auf 1 gesetzt.