我有一个批处理文件,它使用不同的参数反复调用相同的可执行文件。如果其中一个调用返回任何级别的错误代码,如何立即终止?
基本上,我想要相当于MSBuild的ContinueOnError=false
。
答案 0 :(得分:263)
检查errorlevel
语句中的if
,然后exit /b
(仅退出 b atch文件,而不是整个cmd.exe进程) 0以外的值。
same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%
如果您希望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批处理中没有全局“on error goto”类型的构造。我也按照CodeMonkey更新了我的代码,尽管我在XP或Vista上的任何批处理攻击中都没有遇到负面的错误级别。
答案 1 :(得分:230)
为每一行添加|| 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%
答案 2 :(得分:76)
最短的:
command || exit /b
如果需要,您可以设置退出代码:
command || exit /b 666
您还可以登录:
command || echo ERROR && exit /b
答案 3 :(得分:24)
一次小更新,您应该将“if errorlevel 1”的检查更改为以下内容...
IF %ERRORLEVEL% NEQ 0
这是因为在XP上你可以得到负数作为错误。 0 =没有问题,其他任何问题。
请记住DOS处理“IF ERRORLEVEL”测试的方式。如果您要检查的数字是该数字或更高,它将返回true,因此如果您要查找特定的错误编号,则需要以255开头并减少工作。
答案 4 :(得分:10)
以下是BASH和Windows CMD的polyglot program,它运行一系列命令,如果其中任何一个命令失败,则退出:
#!/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%
我过去曾使用过这种类型的东西来制作多平台continuous integration脚本。
答案 5 :(得分:6)
我更喜欢OR形式的命令,因为我发现它们最易读(如
而不是在每个命令之后都加上if)。但是,幼稚的方式
这样做command || exit /b %ERRORLEVEL%
是错误。
这是因为第一次读取一行时批处理会扩展变量,而不是
比使用它们时要多。这意味着如果该行中的command
上面的操作失败,批处理文件会正确退出,但是会以返回码0退出,
因为那是%ERRORLEVEL%
的值在开始时
线。显然,这在我们的脚本中是不可取的,因此我们必须启用
delayed expansion,就像这样:
SETLOCAL EnableDelayedExpansion
command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!
此代码段将执行命令1-4,如果其中任何一个失败,它将 以与失败命令相同的退出代码退出。
答案 6 :(得分:2)
我们不能总是依赖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)
答案 7 :(得分:1)
无论我如何尝试,即使msbuild失败,errorlevel也始终保持为0。所以我建立了我的解决方法:
构建项目并将日志保存到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%"
如果找不到字符串,则错误> 0,构建失败
if "%result%"=="0" ( echo "build failed" )
该解决方案的灵感来自Mechaflash在How to set commands output as a variable in a batch file
的帖子答案 8 :(得分:0)
只需使用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
如果您需要,可以使用以下链接获取更多信息:Errorlevels
答案 9 :(得分:-2)
@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