Quel cmd.les commandes internes d'exe éliminent le niveau D'erreur à 0 en cas de succès?

une méthode fréquente pour traiter les erreurs dans les scripts Windows batch est d'utiliser des choses comme

if errorlevel 1 ... ou if %errorlevel% neq 0 ... . Souvent, on veut que le code de gestion des erreurs préserve le niveau D'erreur.

je crois que toutes les commandes externes auront toujours pour résultat de régler ERRORLEVEL à une certaine valeur, donc le code de gestion des erreurs doit préserver ERRORLEVEL dans une variable d'environnement avant d'exécuter une commande externe.

Mais qu'commandes internes? Le problème est que certaines commandes internes éliminent le niveau D'erreur à 0 lorsqu'elles réussissent, et d'autres non. Et je ne trouve aucune documentation spécifiant quelles commandes font quoi.

donc la question Est, quelles commandes internes effacer le niveau D'erreur à 0 après le succès? c'est pas une question générale sur les codes ERRORLEVEL retournés, mais strictement sur le succès des résultats.

il y a des messages comme Quelle est la meilleure façon de réinitialiser ERRORLEVEL à zéro? et fichiers Windows batch:.bat vs .cmd? qui donnent des réponses partielles. Mais je n'ai jamais vu une liste exhaustive.

Note: j'ai été curieux à ce sujet pendant des années. Donc j'ai finalement décidé de faire un tas d'expériences et de trouver un réponse définitive. Je poste cette Q & R pour partager ce que j'ai trouvé.

21
demandé sur Community 2016-01-23 22:46:13

2 réponses

cette réponse est basée sur des expériences que j'ai passées sous Windows 10. Je doute qu'il y ait des différences avec les versions précédentes de Windows qui utilisent cmd.exe, mais c'est possible.

note également-cette réponse ne tente pas de documenter le résultat du niveau D'erreur lorsqu'une commande interne rencontre une erreur (à l'exception d'un petit bit concernant DEL et ERASE)

non seulement il y a une différence entre les commandes, mais une seule commande peut se comporter différemment selon qu'elle a été exécutée à partir de la ligne de commande, ou à l'intérieur d'un script de lot avec une extension .bat , ou à l'intérieur d'un script de lot avec une extension .cmd .

l'ensemble de commandes suivant n'autorise jamais le niveau D'erreur à 0 en cas de succès, quel que soit le contexte, mais préserve plutôt le niveau d'erreur précédent:

  • BREAK
  • CLS
  • ECHO
  • ENDLOCAL
  • pour: évidemment, les commandes dans la clause DO peuvent définir le niveau D'erreur, mais un FOR réussi avec au moins une itération ne définit pas le niveau d'erreur à 0 seul.
  • GOTO
  • IF: évidemment, les commandes exécutées par IF peuvent définir le niveau D'erreur, mais un IF réussi ne définit pas le niveau d'erreur à 0 en lui-même.
  • KEYS
  • PAUSE
  • POPD
  • RD
  • REM
  • RMDIR
  • SHIFT
  • START
  • titre

l'ensemble suivant de commandes toujours effacer le niveau D'erreur à 0 en cas de succès, quel que soit le contexte:

  • CD
  • CHDIR
  • couleur
  • COPY
  • DATE
  • DEL: efface toujours ERRORLEVEL, même si le DEL échoue (sauf lorsqu'il est exécuté sans aucun argument de fichier) .
  • DIR
  • effacer: efface toujours le niveau D'erreur, même si L'effacement échoue. (sauf lorsqu'il est exécuté sans aucun argument de fichier) .
  • MD
  • MKDIR
  • MKLINK
  • MOVE
  • PUSHD
  • REN
  • RENAME
  • SETLOCAL
  • TIME
  • TYPE
  • VER
  • VERIFY
  • VOL

alors il y a ces commandes qui ne permettent pas de corriger le niveau D'erreur en cas de succès si elles sont émises à partir de la ligne de commande ou à l'intérieur d'un script avec une extension .bat , mais effacez le niveau D'erreur à 0 s'il provient d'un script avec une extension .cmd . Voir https://stackoverflow.com/a/148991/1012053 et https://groups.google.com/forum/#!msg / microsoft.public.win2000.cmdprompt.admin / XHeUq8oe2wk / LIEViGNmkK0J pour plus d'informations.

  • ASSOC
  • DPATH
  • FTYPE
  • chemin
  • PROMPT
  • SET

enfin, il y a ces commandes qui ne s'inscrivent parfaitement dans aucune des catégories précédentes:

  • appel : si un script :routine ou Lot est appelé, alors ERRORLEVEL est exclusivement contrôlé par le script appelé ou :routine. Mais n'importe quel autre type d'appel réussi à une commande va toujours effacer le niveau D'erreur à 0 si L'appelé la commande ne la règle pas autrement.

    Exemple: call echo OK .

  • SORTIE : Si utilisé sans /B , puis le cmd.la session exe se termine et il n'y a plus D'ERRORLEVEL, juste le cmd.exe code de retour. Évidemment EXIT /B 0 efface le niveau D'erreur à 0, mais EXIT /B sans valeur préserve le niveau d'erreur précédent.

je crois que les comptes pour tous les internes commandes, sauf s'il y a une commande non documentée que j'ai manquée.

21
répondu dbenham 2017-05-23 11:54:48

votre description de la commande CALL est incomplète:

appel: efface le niveau D'erreur si la commande appelée ne le définit pas autrement. Exemple: call echo OK .

cochez ce petit exemple:

@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

sortie:

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

CALL description devrait dire quelque chose comme ceci:

  • CALL: Clears ERRORLEVEL si la commande appelée ne la définit pas autrement. Exemple: call echo OK , mais si la commande appelée est une sous-routine, elle préserve le niveau d'erreur précédent. Si le sous-programme appelé n'existe pas, il fixe le niveau D'erreur à 1.
4
répondu Aacini 2016-01-24 11:43:31