web-dev-qa-db-fra.com

Comment faire en sorte qu'un fichier de commandes se termine lorsqu'il rencontre une erreur?

J'ai un fichier de commandes qui appelle le même exécutable à plusieurs reprises avec des paramètres différents. Comment puis-je le faire terminer immédiatement si l'un des appels retourne un code d'erreur de n'importe quel niveau?

En gros, je veux l'équivalent de ContinueOnError=false de MSBuild.

264
Josh Kodroff

Vérifiez la errorlevel dans une instruction if, puis exit /b (quittez le fichier b uniquement, pas processus complet cmd.exe) pour des valeurs autres que 0.

same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%

Si vous souhaitez que la valeur du niveau d'erreur se propage en dehors de votre fichier de commandes

if %errorlevel% neq 0 exit /b %errorlevel%

mais si cela se trouve à l'intérieur d'une for cela devient un peu délicat. Vous aurez besoin de quelque chose de plus comme:

setlocal enabledelayedexpansion
for %%f in (C:\Windows\*) do (
    same-executable-over-and-over.exe /with different "parameters"
    if !errorlevel! neq 0 exit /b !errorlevel!
)

Edit: Vous devez vérifier l'erreur après chaque commande. Il n'y a pas de type global de construction "on got got" dans le lot cmd.exe/command.com. J'ai également mis à jour mon code CodeMonkey , bien que je n'ai jamais rencontré de niveau d'erreur négatif dans aucun de mes traitements par lots sur XP ou sur Vista.

271
system PAUSE

Ajoutez || goto :label à chaque ligne, puis définissez un :label.

Par exemple, créez ce fichier .cmd:

@echo off

echo Starting very complicated batch file...
ping -invalid-arg || goto :error
echo OH noes, this shouldn't have succeeded.
goto :EOF

:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%

Voir aussi question sur la sous-routine de fichier de commandes existante .

235
Fowl

Le plus court:

command || exit /b

Si vous avez besoin, vous pouvez définir le code de sortie:

command || exit /b 666

Et vous pouvez aussi vous connecter:

command || echo ERROR && exit /b
80
Benoit Blanchon

Une mise à jour mineure, vous devriez changer les vérifications pour "si le niveau d'erreur 1" à la suivante ...

IF %ERRORLEVEL% NEQ 0 

En effet, sur XP, vous pouvez obtenir des nombres négatifs sous forme d’erreurs. 0 = pas de problèmes, tout le reste est un problème.

Et gardez à l'esprit la façon dont DOS gère les tests "IF ERRORLEVEL". Il retournera la valeur true si le nombre que vous recherchez est supérieur ou égal à ce nombre. Par conséquent, si vous recherchez des numéros d'erreur spécifiques, vous devez commencer par 255 et réduire les effectifs.

24
Mike Bethany

Voici un programme polyglot pour BASH et Windows CMD qui exécute une série de commandes et se ferme en cas d'échec de l'une d'entre elles:

#!/bin/bash 2> nul

:; set -o errexit
:; function goto() { return $?; }

command 1 || goto :error

command 2 || goto :error

command 3 || goto :error

:; exit 0
exit /b 0

:error
exit /b %errorlevel%

J'ai utilisé ce genre de chose dans le passé pour une plate-forme multiple intégration continue script.

12
Erik Aronesty

Je préfère la forme de commande OR, car je la trouve la plus lisible (au lieu d'avoir un if après chaque commande). Cependant, la manière naïve de le faire, command || exit /b %ERRORLEVEL% est faux .

Cela est dû au fait que le traitement par lots développe les variables lors de la première lecture d'une ligne, plutôt que lors de leur utilisation. Cela signifie que si la variable command de la ligne ci-dessus échoue, le fichier de commandes se ferme correctement, mais avec le code de retour 0, car il s'agit de la valeur de %ERRORLEVEL% au début de la ligne. Évidemment, cela n’est pas souhaitable dans notre script, nous devons donc activer expansion retardée , comme ceci:

SETLOCAL EnableDelayedExpansion

command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!

Cet extrait exécutera les commandes 1 à 4 et, si l'une d'entre elles échoue, il se fermera avec le même code de sortie que la commande ayant échoué.

8
Xarn

Peu importe comment j'ai essayé, errorlevel reste toujours à 0 même lorsque msbuild a échoué. J'ai donc construit ma solution de contournement:

Construire le projet et enregistrer le journal dans Build.log

SET Build_Opt=/flp:summary;logfile=Build.log;append=true

msbuild "myproj.csproj" /t:rebuild /p:Configuration=release /fl %Build_Opt%

recherchez la chaîne "0 Erreur" dans le journal de construction, définissez le résultat sur var

FOR /F "tokens=* USEBACKQ" %%F IN (`find /c /i "0 Error" Build.log`) DO (
    SET var=%%F
)
echo %var%

obtenir le dernier caractère, qui indique combien de lignes contiennent la chaîne de recherche

set result=%var:~-1%

echo "%result%"

si la chaîne n'est pas trouvée, alors erreur> 0, la construction a échoué

if "%result%"=="0" ( echo "build failed" )

Cette solution a été inspirée par la publication de Mechaflash sur Comment définir les commandes en tant que variable dans un fichier de traitement par lots

et https://ss64.com/nt/syntax-substring.html

1
E.Seven

Nous ne pouvons pas toujours compter sur ERRORLEVEL car plusieurs fois des programmes externes ou des scripts batch ne renvoient pas les codes de sortie.

Dans ce cas, nous pouvons utiliser des contrôles génériques pour les échecs suivants:

IF EXIST %outfile% (DEL /F %outfile%)
CALL some_script.bat -o %outfile%
IF NOT EXIST %outfile%  (ECHO ERROR & EXIT /b)

Et si le programme génère quelque chose sur la console, nous pouvons également le vérifier.

some_program.exe 2>&1 | FIND "error message here" && (ECHO ERROR & EXIT /b)
some_program.exe 2>&1 | FIND "Done processing." || (ECHO ERROR & EXIT /b)
1
Amr Ali

Utilisez simplement ERRORLEVEL pour obtenir le résultat souhaité. Il existe deux variables dans la commande ERRORLEVEL permettant de déterminer si un processus a échoué ou réussi. Ces variables sont ERRORLEVEL 0 et ERRORLEVEL 1 (1 pour échec, 0 pour réussite). Voici un exemple d'utilisation de ce fichier dans un fichier batch:

echo off
cls
ping localhost 
errorlevel 0 goto :good
errorlevel 1 goto :bad

:good
cls
echo Good!
echo[
pause
exit

:bad
cls
echo Bad!
echo[
pause
exit

Voici un lien avec plus d'informations si vous en avez besoin: Errorlevels

0
PryroTech