遇到错误如何使批处理文件终止
我有一个批处理文件,使用不同的参数反复调用同一可执行文件。 如果其中一个调用返回任何级别的错误代码,如何使其立即终止?
基本上,我想要等效于MSBuild的ContinueOnError=false。
相关讨论 哪个命令外壳将运行您的脚本? DOS / Win9xs command.com或Win2k + s cmd.exe? 既然这与众不同,那么您能否在编辑问题时加以澄清?
检查if语句中的errorlevel,然后检查exit /b(仅退出批处理文件,而不退出整个cmd.exe进程)以获取非0的值。
12same-executable-over-and-over.exe /with different”parameters”if %errorlevel% neq 0 exit /b %errorlevel%
如果您希望错误级别的值传播到批处理文件之外
1if %errorlevel% neq 0 exit /b %errorlevel%
但是,如果它在for内部,则会有些棘手。您将需要更多类似的东西:
12345setlocal enabledelayedexpansionfor %%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批处理中没有全局的”出错时出错”类型的构造。我还按CodeMonkey更新了我的代码,尽管我在XP或Vista上的任何批量黑客攻击中都从未遇到过负面的错误级别。
相关讨论 有没有办法为整个文件声明一次?”出错时转到”或类似内容?+1用于否定错误级别检查。如果脚本因结果否定而静默失败。小心:enabledelayedexpansion是CRITICAL的,if / else或任何其他块也需要InstallUtil失败时返回-1。是的。@ system-PAUSE,如果显示的话,前两个之间有什么区别吗?延迟扩展启用/禁用或命令扩展(neq必需)启用/禁用与使用if not errorlevel 1 exit B无关,如Microsoft在支持文章”使用命令重定向操作符”和cmd窗口中运行if ?的帮助输出中所述。当前错误级别(退出代码)在使用exit B退出批处理文件时保留。注意:带有参数B的exit需要启用命令扩展,请参阅GOTO:EOF返回何处?知道如何将其放在一行吗?我尝试使用&链接命令,但%errorlevel%直到执行完成后才包含Im正在寻找的内容。我真的不知道如何解释这个答案。这是否意味着我只在批处理文件的末尾添加了if %errorlevel% neq 0 exit b %errorlevel%行?@BradLaney,这是一个替代项。说明。当命令行处理您的行时,在处理该行之前,它将所有%variables%替换为其值。因此,当您执行以下操作时:ICauseProblems.bat && if %errorlevel% NEQ 0 echo Failed…用ICauseProblems.bat甚至运行之前的值填充%errorlevel%。当您打开延迟扩展时,现在还可以执行!可变!相反,它们的处理被延迟到实际使用为止。@FabianRling [续。 ^-]因此,您都需要使用setlocal EnableDelayedExpansion,然后使用!ErrorLevel!或任何您想要的变量,而不是%ErrorLevel%。如果您曾经处于一次性状态,则可以执行” cmd / v:on”以在批处理文件之外启用它。实际上,我将命令提示符快捷方式修改为” cmd.exe / v:on&echo延迟扩展:已启用”,因此始终处于打开状态。只是不要以为其他人有这个,因为它可能实际上并不常见,只有我=(….如果你想成为一个酷酷的人,几乎像我这样的悲伤面孔结束他的工作,那就走吧!=?)? =(。尼斯。我撒谎了,现在我不能编辑我说的内容= /要像我说的那样启动cmd.exe,您需要做的事情:cmd.exe v:on k”echo Delayed Expansion: Enabled… & echo.无论做什么,只要不做我实际上发现的事情,就是:我的cmd.exe以此怪物形式启动:cmd.exe v:on k”set”[unlikely]=1″ & (echo. | set p=Delayed Expansion: ) & if”![unlikely]!”==”1″ (echo Enabled^!) else (echo Disabled… =)。我的意思是,它有效…就是这样。
将|| goto :label添加到每一行,然后定义一个:label。
例如,创建此.cmd文件:
12345678910@echo offecho Starting very complicated batch file…ping -invalid-arg || goto :errorecho OH noes, this shouldn’t have succeeded.goto :EOF:errorecho Failed with error #%errorlevel%.exit /b %errorlevel%
另请参阅有关退出批处理文件子例程的问题。
相关讨论 比” if-errorlevel”更好,更有用!如果错误级别更明确,则此||事情似乎很烂。在大多数shell脚本语言中,这是一个非常常见的习惯用法,它读起来很不错:”执行此操作,否则将失败。”我使用SET来手动跟踪行号:command || (SET ErrorLine=102 && goto :error)@MarcelValdezOrozco在我看来,这就是||最初创建的目的。也许不是特别地转到goto,而是像Fowl所说的”尝试,在出错时执行此操作”。我的问题是这对所有非零退出代码都有效吗?只积极?@ jpmc26是的,向您自己证明-cmd k exit -1 && echo success || echo fail-打印失败。您甚至可以避免使用command || exit b %errorlevel%之类的标签这在Debian软件包中也很常用
最短的:
1command || exit /b
如果需要,可以设置退出代码:
1command || exit /b 666
您还可以登录:
1command || echo ERROR && exit /b 相关讨论 对于错误日志,可以使用STRERR,例如:>&2 echo ERROR …退出/ b偶然返回失败的原始退出代码吗?@FrankSchwieterman,是的,调用exit b时未触及%ERRORLEVEL%,因此将转发错误代码
一个较小的更新,您应该将” if errorlevel 1″的检查更改为以下内容:
1IF %ERRORLEVEL% NEQ 0
这是因为在XP上您会得到负数作为错误。 0 =没问题,其他都是问题。
并记住DOS处理” IF ERRORLEVEL”测试的方式。如果您要检查的数字是该数字或更高,它将返回true,因此,如果您要查找特定的错误号,则需要从255开始并向下计算。
相关讨论 Windows标准内部和外部命令都不会以负值退出。 Microsoft警告任何程序编写者都必须使用负值退出,例如MSDN上有关Environment.ExitCode属性的文章。实际上,必须始终找出应用程序成功使用了哪些退出代码,以及各种错误所导致的退出代码,有关用户期望的否定MS示例,请参见HTML Help Workshop在成功编译.chm文件后返回错误。
这是用于BASH和Windows CMD的多语言程序,该程序运行一系列命令并在其中任何一个失败时退出:
12345678910111213141516#!/bin/bash 2> nul:; set -o errexit:; function goto() { return $?; }command 1 || goto :errorcommand 2 || goto :errorcommand 3 || goto :error:; exit 0exit /b 0:errorexit /b %errorlevel%
过去,我已经将这种类型的东西用于多平台持续集成脚本。
相关讨论 双标签:error是否正确?@riezebosch不,已解决,谢谢…它没有影响结果…第二个标签仅覆盖了第一个
我更喜欢OR形式的命令,因为我发现它们最易读(如而不是在每个命令之后都加上if)。但是,幼稚的方式这样做command || exit /b %ERRORLEVEL%是错误的。
这是因为第一次读取一行时批处理会扩展变量,而不是比使用它们时要多。这意味着如果command在行中上面的操作失败,批处理文件会正确退出,但是会以返回码0退出,因为那是%ERRORLEVEL%的值在线。显然,这在我们的脚本中是不可取的,因此我们必须启用延迟扩展,如下所示:
123456SETLOCAL EnableDelayedExpansioncommand-1 || exit /b !ERRORLEVEL!command-2 || exit /b !ERRORLEVEL!command-3 || exit /b !ERRORLEVEL!command-4 || exit /b !ERRORLEVEL!
该代码段将执行命令1-4,如果其中任何一个失败,它将使用与失败命令相同的退出代码退出。
无论我如何尝试,即使msbuild失败,错误级别也始终保持为0。所以我建立了解决方法:
生成项目并将日志保存到Build.log
123SET Build_Opt=/flp:summary;logfile=Build.log;append=truemsbuild”myproj.csproj” /t:rebuild /p:Configuration=release /fl %Build_Opt%
在构建日志中搜索” 0错误”字符串,将结果设置为var
1234FOR /F”tokens=* USEBACKQ” %%F IN (`find /c /i”0 Error” Build.log`) DO ( SET var=%%F)echo %var%
获取最后一个字符,该字符指示包含搜索字符串的行数
123set result=%var:~-1%echo”%result%”
如果找不到字符串,则错误> 0,构建失败
1if”%result%”==”0″ ( echo”build failed” )
该解决方案的灵感来自Mechaflash在如何将命令输出设置为批处理文件中的变量的文章中
和https://ss64.com/nt/syntax-substring.html
相关讨论 仅适用于计数lss少于十。更好; for f %%F in (type build.log^|find c i”0 Error”) do set result=%%F。注意:find”0 Error”也将找到10 Errors。
我们不能总是依赖ERRORLEVEL,因为很多时候外部程序或批处理脚本不会返回退出代码。
在这种情况下,我们可以对此类失败使用常规检查:
123IF EXIST %outfile% (DEL /F %outfile%)CALL some_script.bat -o %outfile%IF NOT EXIST %outfile% (ECHO ERROR & EXIT /b)
而且,如果程序输出了一些要控制台的内容,我们也可以对其进行检查。
12some_program.exe 2>&1 | FIND”error message here” && (ECHO ERROR & EXIT /b)some_program.exe 2>&1 | FIND”Done processing.” || (ECHO ERROR & EXIT /b)
只需使用errorlevel即可获得所需的结果。 errorlevel命令中有两个变量将确定进程是失败还是成功,这些变量是ERRORLEVEL 0和ERRORLEVEL 1(1表示失败,0表示通过)。这是关于如何在批处理文件中使用的示例:
12345678910111213141516171819echo offclsping localhost errorlevel 0 goto :gooderrorlevel 1 goto :bad:goodclsecho Good!echo[pauseexit:badclsecho Bad!echo[pauseexit
如果需要,这里是带有更多信息的链接:错误级别
相关讨论 这是非常糟糕的,因为答案完全错误。没有命令errorlevel。必须使用IF命令。上一个命令或应用程序的退出代码(错误级别)的测试顺序很重要,因为if errorlevel 0表示退出代码是否等于或大于0。ping localhost总是成功的(除非在文件主机中修改了localhost)。最好是阅读Microsoft支持文章”测试批处理文件中的特定错误级别”,而不是此答案。
123456789101112131415161718192021222324252627@echo offset startbuild=%TIME%C:WINDOWSMicrosoft.NETFrameworkv3.5msbuild.exe c:link.xml /flp1:logfile=c:linkerrors.log;errorsonly /flp2:logfile=c:linkwarnings.log;warningsonly || goto :errorcopy c:app_offline.htm”\lawpccnweb01d$websitesOperationsLinkWebapp_offline.htm”del \lawpccnweb01d$websitesOperationsLinkWebbin /Qecho Start Copy: %TIME%set copystart=%TIME%xcopy C:link_PublishedWebsitesOperationsLink \lawpccnweb01d$websitesOperationsLinkWeb /s /y /ddel \lawpccnweb01d$websitesOperationsLinkWebapp_offline.htmecho Started Build: %startbuild%echo Started Copy: %copystart%echo Finished Copy: %TIME%c:linkwarnings.log:errorc:linkerrors.log 相关讨论 请在您的答案中添加更多信息。仅仅一段代码不是很有帮助。除了未添加任何注释外,您的代码段看起来也不是解释功能的理想人选:它似乎包含许多与问题完全无关的内容。