Comment puis-je terminer un fichier de commandes en cas d’erreur?

J’ai un fichier de commandes qui appelle le même exécutable avec des parameters différents. Comment puis-je le faire cesser immédiatement si l’un des appels renvoie un code d’erreur de n’importe quel niveau?

Fondamentalement, je veux l’équivalent de ContinueOnError=false de MSBuild.

Vérifiez le niveau d’ errorlevel dans une instruction if , puis exit /b (quittez le fichier Batch uniquement, pas l’intégralité du processus 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 de errorlevel se propage en dehors de votre fichier de commandes

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

mais si c’est à l’intérieur d’un, 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 de construction global “en cas d’erreur” dans le fichier cmd.exe / command.com. J’ai également mis à jour mon code par CodeMonkey , même si je n’ai jamais rencontré de niveau d’erreur négatif dans aucun de mes piratages par lot sous XP ou Vista.

Ajouter || goto :label || goto :label chaque ligne, puis définissez une :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 la question sur la sortie du sous-programme de fichiers de commandes .

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 également vous connecter:

 command || echo ERROR && exit /b 

Une mise à jour mineure, vous devez changer les vérifications pour “si errorlevel 1” à la suivante …

 IF %ERRORLEVEL% NEQ 0 

C’est parce que sous XP, vous pouvez obtenir des nombres négatifs en tant qu’erreurs. 0 = pas de problèmes, tout le rest est un problème.

Et gardez à l’esprit la manière dont DOS gère les tests “IF ERRORLEVEL”. Il retournera true si le nombre que vous vérifiez est ce nombre ou supérieur, donc si vous cherchez des numéros d’erreur spécifiques, vous devez commencer par 255 et travailler vers le bas.

Voici un programme polyglotte pour BASH et Windows CMD qui exécute une série de commandes et se ferme si l’un d’entre eux échoue:

 #!/bin/bash 2> nul :; set -o errexit :; function goto() { return $?; } command 1 || goto :error command 2 || goto :error command 3 || goto :error :error :; exit 0 exit /b 0 :error exit /b %errorlevel% 

J’ai utilisé ce type de chose par le passé pour un script d’ continuous integration à plates-formes multiples.

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

Dans ce cas, nous pouvons utiliser des vérifications génériques pour les échecs comme celui-ci:

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

Et si le programme produit quelque chose à consoler, nous pouvons le vérifier également.

 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) 

Je préfère la forme de commande OR, car je les trouve plus lisibles (par opposition à une si après chaque commande). Cependant, la façon naïve de faire cela, command || exit /b %ERRORLEVEL% command || exit /b %ERRORLEVEL% est faux .

En effet, 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 command dans la ligne ci-dessus échoue, le fichier batch se ferme correctement, mais il se termine par le code retour 0, car c’est ce que la valeur de %ERRORLEVEL% était au début de la ligne. Evidemment, cela n’est pas souhaitable dans notre script, nous devons donc activer l’ expansion différé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écute les commandes 1 à 4, et si l’un d’entre eux échoue, il se terminera avec le même code de sortie que la commande défaillante.

Même si j’ai essayé, le errorlevel rest toujours à 0 même si msbuild a échoué. J’ai donc construit ma solution de contournement:

Construire un 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 Error” 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 contient la chaîne de recherche

 set result=%var:~-1% echo "%result%" 

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

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

Cette solution a été inspirée par la publication de Mechaflash intitulée Comment définir la sortie des commandes en tant que variable dans un fichier de commandes.

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

Utilisez simplement ERRORLEVEL pour obtenir le résultat souhaité. Il y a deux variables dans la commande ERRORLEVEL qui détermineraient si un processus a échoué ou a réussi, ces variables sont ERRORLEVEL 0 et ERRORLEVEL 1 (1 pour échec, 0 pour réussite). Voici un exemple sur la façon dont cela serait utilisé 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:

 @echo off set startbuild=%TIME% C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe c:\link.xml /flp1:logfile=c:\link\errors.log;errorsonly /flp2:logfile=c:\link\warnings.log;warningsonly || goto :error copy c:\app_offline.htm "\\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm" del \\lawpccnweb01\d$\websites\OperationsLinkWeb\bin\ /Q echo Start Copy: %TIME% set copystart=%TIME% xcopy C:\link\_PublishedWebsites\OperationsLink \\lawpccnweb01\d$\websites\OperationsLinkWeb\ /s /y /d del \\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm echo Started Build: %startbuild% echo Started Copy: %copystart% echo Finished Copy: %TIME% c:\link\warnings.log :error c:\link\errors.log