Как сделать пакетный файл завершенным после возникновения ошибки?

У меня есть пакетный файл, который много раз вызывает один и тот же исполняемый файл с разными параметрами. Как заставить его немедленно прекратить работу, если один из вызовов возвращает код ошибки любого уровня?

В принципе, я хочу эквивалент MSBuild ContinueOnError=false.

Ответ 1

Проверьте errorlevel в операторе if, а затем exit /b (закройте только файл b, а не весь процесс cmd.exe) для значений, отличных от 0.

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

Если вы хотите, чтобы значение уровня ошибок распространялось вне вашего пакетного файла

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

но если он находится внутри for, он становится немного сложным. Вам понадобится нечто большее:

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

Изменить: Вы должны проверить ошибку после каждой команды. В cmd.exe/command.com не существует глобального типа "с ошибкой goto". Я также обновил свой код в CodeMonkey, хотя я никогда не сталкивался с отрицательным уровнем ошибок в любом из моих пакетных взломов на XP или Vista.

Ответ 2

Добавьте || goto :label в каждую строку, а затем определите :label.

Например, создайте этот .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%

См. также вопрос об окончании подпрограммы пакетного файла.

Ответ 3

Самый короткий:

command || exit /b

Если вам нужно, вы можете установить код выхода:

command || exit /b 666

И вы также можете зарегистрировать:

command || echo ERROR && exit /b

Ответ 4

Одно небольшое обновление, вы должны изменить проверки на "if errorlevel 1" на следующее...

IF %ERRORLEVEL% NEQ 0 

Это потому, что на XP вы можете получить отрицательные числа как ошибки. 0 = нет проблем, что-то еще проблема.

И помните, как DOS обрабатывает тесты "IF ERRORLEVEL". Он вернет true, если число, которое вы проверяете, - это номер или выше, поэтому, если вы ищете конкретные номера ошибок, вам нужно начать с 255 и работать вниз.

Ответ 5

Вот для BASH и Windows CMD, которая запускает ряд команд и завершает работу, если какой-либо из них не работает:

#!/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%

Я использовал этот тип в прошлом для множественной платформы непрерывная интеграция script.

Ответ 6

Независимо от того, как я пытался, уровень ошибок всегда остается 0, даже если msbuild не удалось. Поэтому я построил свое решение:

Создайте проект и сохраните журнал в Build.log

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

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

найдите строку "0 Ошибка" в журнале построения, установите результат в var

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

получить последний символ, который указывает, сколько строк содержит строку поиска

set result=%var:~-1%

echo "%result%"

если строка не найдена, тогда ошибкa > 0, ошибка сборки

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

Это решение было вдохновлено сообщением Мечафлаша в Как установить команды в качестве переменной в пакетном файле

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

Ответ 7

Мы не всегда можем зависеть от ERRORLEVEL, потому что много раз внешние программы или пакетные скрипты не возвращают коды выхода.

В этом случае мы можем использовать общие проверки для таких сбоев:

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

И если программа выводит что-то на консоль, мы также можем проверить ее.

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)

Ответ 8

Просто используйте ERRORLEVEL для достижения желаемого результата. В команде ERRORLEVEL есть две переменные, которые определяли бы, был ли процесс неудачным или преуспел, эти переменные ERRORLEVEL 0 и ERRORLEVEL 1 (1 для отказа, 0 для прохода). Вот пример того, как это будет использоваться в пакетном файле:

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

Вот ссылка с дополнительной информацией, если вам это нужно: Уровни ошибок

Ответ 9

@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