在 Windows 批处理文件中检查非零(错误)返回码的万无一失的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10935693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:33:57  来源:igfitidea点击:

Foolproof way to check for nonzero (error) return code in windows batch file

windowsbatch-file

提问by Pat

Intro

介绍

There's a lot of advice out there for dealing with return codes in batch files (using the ERROLEVEL mechanism), e.g.

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

Some of the advice is to do if errorlevel 1 goto somethingbad, while others recommend using the %ERRORLEVEL%variable and using ==, EQU, LSS, etc. There seem to be issues within IFstatements and such, so then delayedexpansion is encouraged, but it seems to come with quirks of its own.

一些建议是 do if errorlevel 1 goto somethingbad,而另一些建议使用 %ERRORLEVEL%变量并使用==, EQU,LSS等。IF语句等中似乎存在问题,因此鼓励延迟扩展,但它似乎有其自身的怪癖。

Question

What is a foolproof (i.e. robust, so it will work on nearly any system with nearly any return code) way to know if a bad (nonzero) code has been returned?

什么是万无一失(即健壮,因此它可以在几乎任何具有几乎任何返回代码的系统上工作)方式来知道是否返回了错误(非零)代码?

My attempt

我的尝试

For basic usage, the following seems to work ok to catch any nonzero return code:

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

if not errorlevel 0 (
    echo error level was nonzero
)

回答by dbenham

Sorry, your attempt is not even close. if not errorlevel 0is only true if errorlevel is negative.

抱歉,您的尝试还差得远。if not errorlevel 0仅当 errorlevel 为负时才为真。

If you know that errorlevel will never be negative, then

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

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

If you must allow for negative errorlevel, and are not within a parenthesized block of code, then

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

set "errorlevel=1"
set "errorlevel="
if %errorlevel% neq 0 (echo error level is non-zero)

Note - I edited my answer to explicitly clear any user defined errorlevel value after reading Joey's comment to the linked answer in the question. A user defined errorlevel can mask the dynamic value that we are trying to access. But this only works if your script has a .batextension. Scripts with .cmdextension will set your ERRORLEVEL to 0 if you set or clear a variable! To make matters worse, XP will set ERRORLEVEL to 1 if you attempt to undefine a variable that does not exist. That is why I first explicitly define an ERRORLEVEL variable before I attempt to clear it!

注意 - 在阅读 Joey 对问题中链接答案的评论后,我编辑了我的答案以明确清除任何用户定义的错误级别值。用户定义的错误级别可以屏蔽我们尝试访问的动态值。但这仅在您的脚本具有.bat扩展名时才有效。.cmd如果您设置或清除变量,带有扩展名的脚本会将您的 ERRORLEVEL 设置为 0!更糟糕的是,如果您尝试取消定义一个不存在的变量,XP 会将 ERRORLEVEL 设置为 1。这就是为什么我在尝试清除它之前首先明确定义一个 ERRORLEVEL 变量!

If you are within a parenthesized block of code then you must use delayed expansion to get the current value

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

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

But sometimes you don't want delayed expansion enabled. All is not lost if you want to check the error level immediately after executing a command.

但有时您不希望启用延迟扩展。如果您想在执行命令后立即检查错误级别,一切都不会丢失。

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

If you absolutely must check the dynamic ERRORLEVEL value without using delayed expansion within a parenthesized block, then the following works. But it has the error handling code in two places.

如果您绝对必须检查动态 ERRORLEVEL 值而不使用带括号的块内的延迟扩展,则以下方法有效。但是它在两个地方有错误处理代码。

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


Here, at long last, is the "ultimate" test for non-zero errrolevel that should work under any circumstances :-)


在这里,终于,是在任何情况下都应该工作的非零错误级别的“最终”测试:-)

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

It can even be converted into a macro for ease of use:

为了便于使用,它甚至可以转换为宏:

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

The macro supports parentheses and ELSE just fine:

宏支持括号和 ELSE 就好了:

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


One last issue:


最后一期:

Redirection of input and/or output can fail for any number of reasons. But redirection errors do notset the errorlevel unless the ||operator is used. See File redirection in Windows and %errorlevel%for more information. So one can argue that there does not exist a fool-proof way to check for errors via errorlevel. The most reliable method (but still not infallible) is the ||operator.

由于多种原因,输入和/或输出的重定向可能会失败。但是重定向错误不会设置错误级别,除非使用||运算符。有关详细信息,请参阅Windows 中的文件重定向和 %errorlevel%。因此,人们可以争辩说,不存在通过错误级别检查错误的万无一失的方法。最可靠的方法(但仍然不是绝对可靠的)是||操作符。