Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 如何使批处理文件在遇到错误时终止?_Batch File - Fatal编程技术网

Batch file 如何使批处理文件在遇到错误时终止?

Batch file 如何使批处理文件在遇到错误时终止?,batch-file,Batch File,我有一个批处理文件,它用不同的参数反复调用同一个可执行文件。如果其中一个调用返回任何级别的错误代码,如何使其立即终止 基本上,我需要与MSBuild的ContinueOnError=false等效的检查if语句中的errorlevel,然后检查exit/b(仅退出batch文件,而不是整个cmd.exe进程)中除0以外的值 same-executable-over-and-over.exe /with different "parameters" if %errorlevel% neq 0 ex

我有一个批处理文件,它用不同的参数反复调用同一个可执行文件。如果其中一个调用返回任何级别的错误代码,如何使其立即终止


基本上,我需要与MSBuild的
ContinueOnError=false

等效的检查
if
语句中的
errorlevel
,然后检查
exit/b
(仅退出batch文件,而不是整个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”类型的构造。我还根据更新了我的代码,尽管我在XP或Vista上的批处理黑客攻击中从未遇到过负错误级别。

一个小更新,您应该将“if errorlevel 1”的检查更改为以下内容

IF %ERRORLEVEL% NEQ 0 
这是因为在XP上,您可以将负数作为错误。0=没有问题,其他任何东西都是问题


记住DOS处理“IF ERRORLEVEL”测试的方式。如果您要检查的数字是该数字或更高的数字,则返回true。因此,如果您要查找特定的错误数字,则需要从255开始并向下搜索。

| | goto:label
添加到每行,然后定义
:label

例如,创建此.cmd文件:

@echo关闭
echo正在启动非常复杂的批处理文件。。。
ping-无效参数| |转到:错误
哦,不,这不应该成功。
后藤:EOF
:错误
回显失败,错误为#%errorlevel%。
退出/b%errorlevel%
另请参见。

最短的:

command || exit /b
如果需要,您可以设置退出代码:

command || exit /b 666
您还可以记录:

command || echo ERROR && exit /b

我们不能总是依赖于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)

无论我如何尝试,即使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在

这是一个用于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

:; exit 0
exit /b 0

:error
exit /b %errorlevel%

我过去曾在多平台脚本中使用过这种类型的东西。

我更喜欢命令的或形式,因为我发现它们可读性最好(如 反对在每个命令后使用if)。然而,这种天真的方式 这样做,
命令| |退出/b%ERRORLEVEL%
是错误的

这是因为批处理在第一次读取行时扩展变量,而不是 而不是在使用它们时。这意味着如果行中的
命令
上述操作失败,批处理文件正确退出,但退出时返回代码为0, 因为这就是在测试开始时
%ERRORLEVEL%
的值 线路。显然,这在我们的脚本中是不受欢迎的,因此我们必须启用 ,例如:

SETLOCAL EnableDelayedExpansion

command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!
这个代码段将执行命令1-4,如果其中任何一个失败,它将执行
使用与失败命令相同的退出代码退出。

哪个命令shell将运行您的脚本?DOS/Win9x的command.com还是Win2k+的cmd.exe?既然这是一个不同的世界,你能在编辑你的问题时澄清一下吗?有没有办法在整个文件中声明一次?“On error goto”或类似内容?+1用于负错误级别检查。由于负面结果,脚本在静默状态下失败。请小心:enabledelayedexpansion非常重要,并且对于if/else或任何其他脚本都是必需的block@system-暂停显示的前两个“如果”之间是否有任何区别?启用/禁用延迟扩展或命令扩展(neq需要
neq
)如Microsoft在支持文章和在cmd窗口中运行
if/?
时的帮助输出中所述,启用/禁用对使用
if not errorlevel 1 exit/B并不重要。当前错误级别(退出代码)在使用
exit/B
退出批处理文件时保持不变。注意:
exit
带参数
/B
需要启用命令扩展,请参阅这是大多数shell脚本语言中非常常见的习惯用法,它的内容很好:“执行此操作,或者在失败时执行此操作…”我使用一个集合来手动跟踪行号:
命令| |(SET ErrorLine=102&&goto:error)
@marcelvaldezorzco在我看来,这就是创建
|
的初衷。也许不是特别的去做,但正如福尔所说的“试一下,出错后再做”。我的问题是,这是否适用于所有非零出口代码?只有积极的一面?@jpmc26是的,它确实存在,向自己证明-
cmd/k exit-1&&echo success | | echo fail
-打印失败。您甚至可以使用类似于
命令| | exit/b%errorlevel%
的方法避免标签。请在回答中添加更多信息。仅仅一段代码并没有多大帮助。除了没有添加任何注释之外,您的代码片段似乎不是解释功能的好候选:它似乎包含了许多与问题完全无关的内容。退出/b是否偶然返回了原始失败的退出代码?@FrankSchwieterman,是的,调用
退出/b
时,
%ERRORLEVEL%
未被触动,因此错误代码将被转发Windows标准内部和外部命令中的任何一个都不会以负值退出。Microsoft警告任何程序编写器以负值退出
SETLOCAL EnableDelayedExpansion

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