在Windows批处理文件中检查非零(错误)返回代码的简单方法

22

介绍

有很多关于批处理文件中处理返回代码的建议(使用ERROLEVEL机制),例如:

其中一些建议是执行if errorlevel 1 goto somethingbad,而其他人则建议使用%ERRORLEVEL%变量和使用==EQULSS等符号。似乎在IF语句中存在问题,因此需要使用delayedexpansion,但它似乎带有自己的怪癖。

问题

有没有一种稳妥(即健壮,可以在几乎任何系统上使用,处理几乎所有的返回代码)的方法来知道是否返回了不良(非零)代码?

我的尝试

对于基本用法,以下方法似乎可以捕获任何非零返回代码:

if not errorlevel 0 (
    echo error level was nonzero
)
1个回答

47

很抱歉,你的尝试完全没有接近。 if not errorlevel 0 只有在errorlevel为负数时才为真。

如果你知道errorlevel永远不会是负数,那么

if errorlevel 1 (echo error level is greater than 0)

如果你必须允许负的错误级别,并且不在代码的括号块内,那么

set "errorlevel=1"
set "errorlevel="
if %errorlevel% neq 0 (echo error level is non-zero)
注意 - 在阅读Joey在问题中链接的答案时,我编辑了我的答案以明确清除任何用户定义的errorlevel值。用户定义的errorlevel可能会掩盖我们尝试访问的动态值。但是这仅适用于扩展名为.bat的脚本。扩展名为.cmd的脚本将在设置或清除变量时将ERRORLEVEL设置为0!更糟糕的是,XP将在尝试取消定义不存在的变量时将ERRORLEVEL设置为1。这就是为什么我首先在尝试清除它之前明确定义一个ERRORLEVEL变量的原因!

如果您在代码的括号块内,则必须使用延迟扩展来获取当前值。

setlocal enableDelayedExpansion
(
  SomeCommandThatMightGenerateAnError
  set "errorlevel=1"
  set "errorlevel="
  if !errorlevel! neq 0 (echo error level is non-zero)
)

但有时你不想启用延迟扩展。如果你想在执行命令后立即检查错误级别,也不是完全无法实现。

(
  SomeCommandThatMightGenerateAnError && (echo Success, no error) || (echo There was an error)
)

如果你确实需要在括号块内部不使用延迟扩展来检查动态的ERRORLEVEL值,那么下面的方法可以工作。但是它有两个地方的错误处理代码。

(
  SomeCommandThatMightGenerateAnError
  if errorlevel 1 (echo errorlevel is non-zero) else if not errorlevel 0 (echo errorlevel is non-zero)
)


终于,这里是一个“终极”的非零错误级别测试,它应该在任何情况下都有效 :-)

(
  SomeCommandThatMightGenerateAnError
  set foundErr=1
  if errorlevel 0 if not errorlevel 1 set "foundErr="
  if defined foundErr echo errorlevel is non-zero
)

甚至可以将其转换为宏以便于使用:

set "ifErr=set foundErr=1&(if errorlevel 0 if not errorlevel 1 set foundErr=)&if defined foundErr"
(
  SomeCommandThatMightGenerateAnError
  %ifErr% echo errorlevel is non-zero
)

这个宏可以很好地支持括号和ELSE:

%ifErr% (
  echo errorlevel is non-zero
) else (
  echo errorlevel is zero
)


最后一个问题:

输入和/或输出的重定向可能由于各种原因而失败。但是,只有在使用||运算符时重定向错误才会设置错误级别。有关更多信息,请参见Windows中的文件重定向和%errorlevel%。因此,可以说没有一种绝对可靠的方法来通过错误级别检查错误。最可靠的方法(但仍不完美)是使用||运算符。


4
值得注意的是,errorlevel 不是环境变量。 - Nick Westgate
1
@NickWestgate - 是的,ERRORLEVEL是许多“伪”或“动态”变量之一。我已经确定并记录了三类“动态”变量,网址为https://dev59.com/0mIj5IYBdhLWcg3wilgI#20169219,在那篇文章中,我引用了Raymond Chen博客中的同样内容。 - dbenham
1
编辑 2016-06-03:我修改了代码以清除任何用户定义的ERRORLEVEL,以解决XP行为,如果您尝试未定义不存在的变量,则将ERRORLEVEL设置为1。 - dbenham
在搜索非零错误代码检查时,偶然发现了您的答案。(我正在将一个简短的shell脚本转换为在Windows上运行某些东西)令人惊讶的是,在shell脚本中可以简单地完成以下操作: var=$?; if [ $var -ne 0 ] then #Do something 但在批处理文件中却如此复杂和不直观。 - ranban282

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接