简体   繁体   English

批量转到丢失错误级别

[英]Batch goto loses errorlevel

Consider the following bat, test.bat (PC01 is off): 考虑以下bat,test.bat(PC01关闭):

mkdir \\PC01\\c$\Test || goto :eof

If I run that bat from a command shell: 如果我从命令shell运行该bat:

> test.bat || echo 99
> if ERRORLEVEL 1 echo 55

The output is just 55. No 99. There is an errorlevel, but the || 输出只有55.没有99.有一个错误级别,但是|| operator did not see it. 操作员没有看到它。

If I run that bat using cmd /c - 如果我用cmd /c -运行那个蝙蝠cmd /c -

> cmd /c test.bat || echo 99
> if ERRORLEVEL 1 echo 55

The output is blank. 输出为空白。 Errorlevel is 0. Errorlevel为0。

If I remove the || goto :eof 如果我删除|| goto :eof || goto :eof , everything works as one would predict — ie the output would be || goto :eof ,一切都按照人们的预测 - 即输出即可

99 55 99 55

Does anyone know why this half-baked semi-existent ERRORLEVEL behaviour is occurring? 有谁知道为什么这种半生半熟的ERRORLEVEL行为正在发生?

In most circumstances, || 在大多数情况下, || is the most reliable way to detect an error . 是检测错误的最可靠方法 But you have stumbled on one of the rare cases where ERRORLEVEL works but || 但你偶然发现ERRORLEVEL工作的罕见情况之一,但是|| does not. 才不是。

The problem stems from the fact that your error is raised within a batch script, and || 问题源于您在批处理脚本和||引发错误的事实 responds to the return code of the most recently executed command. 响应最近执行的命令的返回码。 You are thinking of test.bat as a single "command", but actually it is a sequence of commands. 您正在考虑将test.bat作为单个“命令”,但实际上它是一系列命令。 The last command executed within the script is GOTO :EOF , and that executed successfully. 脚本中执行的最后一个命令是GOTO :EOF ,并且执行成功。 So your test.bat||echo 99 is responding to the success of the GOTO :EOF . 所以你的test.bat||echo 99正在响应GOTO :EOF的成功。

When you remove the ||GOTO :EOF from within the script, then your test.bat||echo99 sees the result of the failed mkdir . 当你从脚本中删除||GOTO :EOF ,你的test.bat||echo99看到失败的mkdir的结果。 But if you were to add a REM command to the end of test.bat, then test.bat||echo 99 would respond to the success of the REM , and the error would be masked again. 但是如果要在test.bat的末尾添加REM命令,那么test.bat||echo 99将响应REM的成功,并且错误将再次被屏蔽。

The ERRORLEVEL is still non-zero after test.bat||echo 99 because commands like GOTO and REM do not clear any prior non-zero ERRORLEVEL upon success. test.bat||echo 99之后,ERRORLEVEL仍为非零,因为GOTOREM类的命令在成功时不会清除任何先前的非零ERRORLEVEL。 This is one of many pieces of evidence that ERRORLEVEL and the return code are not quite the same thing. 这是ERRORLEVEL和返回代码不完全相同的许多证据之一。 It definitely gets confusing. 它肯定会让人感到困惑。

You can treat test.bat as a unit command and get the behavior you want by using CALL. 您可以将test.bat视为单元命令,并使用CALL获取所需的行为。

C:\test>call test.bat && echo OK || echo FAIL
FAIL

C:\test>if ERRORLEVEL 1 (echo FAIL2) else echo OK2
FAIL2

This works because the CALL command temporarily transfers control to the called script. 这是有效的,因为CALL命令暂时将控制转移到被调用的脚本。 When the script terminates, control is returned to the CALL command, and it returns the current ERRORLEVEL. 当脚本终止时,控制权返回到CALL命令,并返回当前的ERRORLEVEL。 So ||echo 99 is responding to the error returned by the CALL command itself, not the last command within the script. 所以||echo 99响应CALL命令本身返回的错误,而不是脚本中的最后一个命令。

Now for the CMD /C issue. 现在讨论CMD /C问题。

The return code returned by CMD /C is the return code of the last command executed. CMD /C返回的返回码是最后执行的命令的返回码。

This works: 这有效:

C:\test>cmd /c call test.bat && echo OK || echo FAIL
FAIL

C:\test>if ERRORLEVEL 1 (echo FAIL2) else echo OK2
FAIL2

because CMD /C returns the ERRORLEVEL returned by the CALL statement 因为CMD /C返回CALL语句返回的ERRORLEVEL

But this fails entirely: 但这完全失败了:

C:\test>cmd /c test.bat && echo OK || echo FAIL
OK

C:\test>if ERRORLEVEL 1 (echo FAIL2) else echo OK2
OK2

Without the CALL , the CMD /C returns the return code of the last executed command, which is the GOTO :EOF . 如果没有CALLCMD /C将返回上次执行的命令的返回码,即GOTO :EOF The CMD /C also sets the ERRORLEVEL to the same return code, so now there is no evidence that there ever was an error within the script. CMD /C还将ERRORLEVEL设置为相同的返回码,因此现在没有证据表明脚本中存在错误。

And down the rabbit hole we go 我们走了兔洞

RLH, in his answer and in his comments to my answer, is concerned that || RLH在他的回答和他对我的回答的评论中担心|| sometimes clears the ERRORLEVEL. 有时会清除ERRORLEVEL。 He provides evidence that appears to back up his conclusion. 他提供的证据似乎支持了他的结论。 But the situation isn't that simple, and it turns out that || 但情况并非如此简单,事实证明|| is the most reliable (but still not perfect) way to detect errors. 是检测错误的最可靠(但仍然不完美)的方法。

As I stated earlier, the return code that all external commands return upon exit is not the same thing as the cmd.exe ERRORLEVEL. 正如我之前所说,退出时所有外部命令返回的返回码与cmd.exe ERRORLEVEL不同。

The ERRORLEVEL is a state maintained within the cmd.exe session itself, wholly distinct from return codes. ERRORLEVEL是cmd.exe会话本身内维护的状态,完全不同于返回代码。

This is even documented in the definition of the exitCode within the EXIT help 这甚至记录在EXIT帮助中的exitCode定义中
( help exit or exit /? ) help exitexit /?

EXIT [/B] [exitCode]

  /B          specifies to exit the current batch script instead of
              CMD.EXE.  If executed from outside a batch script, it
              will quit CMD.EXE

  exitCode    specifies a numeric number.  if /B is specified, sets
              ERRORLEVEL that number.  If quitting CMD.EXE, sets the process
              exit code with that number.

When an external command is run by CMD.EXE, it detects the executeable's return code and sets the ERRORLEVEL to match. 当CMD.EXE运行外部命令时,它会检测可执行文件的返回码并将ERRORLEVEL设置为匹配。 Note that it is only a convention that 0 means success, and non-zero means error. 请注意,只有约定0表示成功,非零表示错误。 Some external commands may not follow that convention. 某些外部命令可能不遵循该约定。 For example, the HELP command (help.exe) does not follow the convention - it returns 0 if you specify an invalid command as in help bogus , but returns 1 if you ask for help on a valid command, as in help rem . 例如,HELP命令(help.exe)不遵循约定 - 如果您在help bogus指定了无效命令,则返回0,但如果您在有效命令上请求帮助,则返回1,如help rem

The || || operator never clears the ERRORLEVEL when an external command is executed. 执行外部命令时,operator永远不会清除ERRORLEVEL。 The process exit code is detected and fires || 检测到进程退出代码并触发|| if it is non-zero, and the ERRORLEVEL will still match the exit code. 如果它不为零,则ERRORLEVEL仍将匹配退出代码。 That being said, the commands that appear after && and/or || 话虽如此,在&&和/或||之后出现的命令 may modify the ERRORLEVEL, so one has to be careful. 可能会修改ERRORLEVEL,所以必须要小心。

But there are many other situations besides external commands where we developers care about success/failure and return codes/ERRORLEVELs. 但除了外部命令之外还有许多其他情况,我们开发人员关心成功/失败和返回代码/ ERRORLEVEL。

  • execution of internal commands 执行内部命令
  • redirection operators < , > , and >> 重定向运算符<>>>
  • execution of batch scripts 执行批处理脚本
  • failed execution of invalid commands 执行无效命令失败

Unfortunately, CMD.EXE is not at all consistent in how it handles error conditions for these situations. 不幸的是,CMD.EXE在如何处理这些情况的错误条件方面并不完全一致。 CMD.EXE has multiple internal points where it must detect errors, presumably through some form of internal return code that is not necessarily the ERRORLEVEL, and at each of these points CMD.EXE is in a position to set the ERRORLEVEL depending on what it finds. CMD.EXE有多个内部点,它必须检测错误,可能是通过某种形式的内部返回代码,不一定是ERRORLEVEL,并且在这些点中的每一个CMD.EXE都可以根据它找到的内容设置ERRORLEVEL 。

For my test cases below, note that (call ) , with a space, is arcane syntax that clears the ERRORLEVEL to 0 before each test. 对于下面的测试用例,请注意(call ) ,带有空格,是一种神秘的语法,在每次测试之前将ERRORLEVEL清除为0。 Later on, I will also use (call) , without a space, to set the ERRORLEVEL to 1 稍后,我还将使用(call) ,没有空格,将ERRORLEVEL设置为1

Also note that delayed expansion has been enabled within my command session by using 另请注意,我的命令会话中已启用延迟扩展
cmd /v: on prior to running my tests cmd /v: on运行测试之前cmd /v: on

The vast majority of internal commands set the ERRORLEVEL to a non-zero value upon failure, and the error condition also fires || 绝大多数内部命令在失败时将ERRORLEVEL设置为非零值,并且错误条件也会触发|| . The || || never clears or modifies the ERRORLEVEL in these cases. 在这些情况下,永远不要清除或修改ERRORLEVEL。 Here are a couple examples: 以下是几个例子:

C:\test>(call ) & set /a 1/0
Divide by zero error.

C:\test>echo !errorlevel!
1073750993

C:\test>(call ) & type notExists
The system cannot find the file specified.

C:\test>echo !errorlevel!
1

C:\test>(call ) & set /a 1/0 && echo OK || echo ERROR !errorlevel!
Divide by zero error.
ERROR 1073750993

C:\test>(call ) & type notExists.txt && echo OK || echo ERROR !errorlevel!
The system cannot find the file specified.
ERROR 1

Then there is at least one command, RD, (possibly more), as well as the redirection operators that fire || 然后至少有一个命令RD,(可能更多),以及触发||的重定向操作符 upon error, but do not set ERRORLEVEL unless || 出错时,除非||否则不要设置ERRORLEVEL is used. 用来。

C:\test>(call ) & rd notExists
The system cannot find the file specified.

C:\test>echo !errorlevel!
0

C:\test>(call ) & echo x >\badPath\out.txt
The system cannot find the path specified.

C:\test>echo !errorlevel!
0

C:\test>(call ) & rd notExists && echo OK || echo ERROR !errorlevel!
The system cannot find the file specified.
ERROR 2

C:\test>(call ) & echo x >\badPath\out.txt && echo OK || echo ERROR !errorlevel!
The system cannot find the path specified.
ERROR 1

See "rd" exits with errorlevel set to 0 on error when deletion fails, etc and File redirection in Windows and %errorlevel% for more information. 如果删除失败,请参阅“rd”退出,错误级别设置为0,等等,以及Windows中的文件重定向和%errorlevel%以获取更多信息。

I know of one internal command (there may be others) plus basic failed I/O operations that can issue error messages to stderr, yet they don't fire || 我知道一个内部命令(可能还有其他命令)加上可以向stderr发出错误消息的基本失败I / O操作,但它们不会触发|| nor do they set a non-zero ERRORLEVEL. 他们也没有设置非零ERRORLEVEL。

The DEL command can print an error if the file is read only, or does not exist, but it does not fire || 如果文件是只读的,或者不存在,DEL命令可以打印错误,但它不会触发|| or set ERRORLEVEL to non-zero 或者将ERRORLEVEL设置为非零

C:\test>(call ) & del readOnlyFile
C:\test\readOnlyFile
Access is denied.

C:\test>echo !errorlevel!
0

C:\test>(call ) & del readOnlyFile & echo OK || echo ERROR !errorlevel!
C:\test\readOnlyFile
Access is denied.
OK

See https://stackoverflow.com/a/32068760/1012053 for a bit more information related to DEL errors. 有关DEL错误的更多信息,请参阅https://stackoverflow.com/a/32068760/1012053

In much the same way, when stdout has been successfully redirected to a file on a USB device, but then the device is removed before a command such as ECHO tries to write to the device, then the ECHO will fail with an error message to stderr, yet || 以同样的方式,当stdout成功重定向到USB设备上的文件,但是在ECHO之类的命令尝试写入设备之前移除设备,则ECHO将失败并向stderr发送错误消息,但是|| does not fire, and ERRORLEVEL is not set to non-zero. 不会触发,并且ERRORLEVEL未设置为非零。 See http://www.dostips.com/forum/viewtopic.php?f=3&t=6881 for more info. 有关详细信息,请参阅http://www.dostips.com/forum/viewtopic.php?f=3&t=6881

Then we have the case where a batch script is executed - the actual subject of the OP's question. 然后我们有一个批处理脚本被执行的情况 - 这是OP问题的实际主题。 Without CALL , The || 没有CALL|| operator responds to the last command executed within the script. 运算符响应脚本中执行的最后一个命令。 With CALL , the || 使用CALL|| operator responds to the value returned by the CALL command, which is the final ERRORLEVEL that exists upon batch termination. 运算符响应CALL命令返回的值,这是批量终止时存在的最终ERRORLEVEL。

Finally, we have the case that RLH reports, where an invalid command is reported as ERRORLEVEL 9009 normally, but as ERRORLEVEL 1 if || 最后,我们有RLH报告的情况,其中无效命令通常报告为ERRORLEVEL 9009,但如果||则报告为ERRORLEVEL 1 is used. 用来。

C:\test>(call ) & InvalidCommand
'InvalidCommand' is not recognized as an internal or external command,
operable program or batch file.

C:\test>echo !errorlevel!
9009

C:\test>(call ) & InvalidCommand && echo OK || echo ERROR !errorlevel!
'InvalidCommand' is not recognized as an internal or external command,
operable program or batch file.
ERROR 1

I can't prove this, but I suspect that the detection of command failure and setting of ERRORLEVEL to 9009 occurs very late in the command execution process. 我无法证明这一点,但我怀疑在命令执行过程中很晚才发现命令失败的检测和ERRORLEVEL设置为9009。 I'm guessing that || 我猜这是|| intercepts the error detection before the 9009 is set, at which point it sets it to 1 instead. 在设置9009之前截取错误检测,此时它将其设置为1。 So I don't think || 所以我不认为|| is clearing the 9009 error, but rather it is an alternate pathway by which the error is handled and set. 正在清除9009错误,而是它是处理和设置错误的备用途径。

An alternate mechanism for this behavior is that the invalid command could always set the ERRORLEVEL to 9009, yet have a different return code of 1. The || 这种行为的另一种机制是无效命令可以在ERRORLEVEL始终设置为9009,但有1不同的返回码|| could subsequently detect the 1 return code and set the ERRORLEVEL to match, thus overwriting the 9009. 随后可以检测到1个返回码并将ERRORLEVEL设置为匹配,从而覆盖9009。

Regardless, I am not aware of any other situation where a non-zero ERRORLEVEL result is different depending on whether || 无论如何,我不知道任何其他情况,根据是否||非零ERRORLEVEL结果会有所不同 was used or not. 是否使用过。

So that takes care of what happens when a command fails. 这样可以处理命令失败时发生的事情。 But what about when an internal command succeeds? 但是内部命令何时成功呢? Unfortunately, CMD.EXE is even less consistent than it was with errors. 不幸的是,CMD.EXE甚至比错误更不一致。 It varies by command, and may also depend on whether it is executed from the command prompt, from a batch script with a .bat extension, or from a batch script with a .cmd extension. 它因命令而异,也可能取决于它是从命令提示符,带有.bat扩展名的批处理脚本还是带有.cmd扩展名的批处理脚本执行的。

I am basing all of the discussion below on Windows 10 behavior. 我基于以下关于Windows 10行为的所有讨论。 I doubt there are differences with earlier Windows versions that use cmd.exe, but it is possible. 我怀疑使用cmd.exe的早期Windows版本存在差异,但这是可能的。

The following commands always clear the ERRORLEVEL to 0 upon success, regardless of context: 无论上下文如何,以下命令在成功时始终将ERRORLEVEL清除为0:

  • CALL : Clears ERRORLEVEL if the CALLed command does not otherwise set it. CALL:如果CALLed命令没有设置它,则清除ERRORLEVEL。
    Example: call echo OK 示例: call echo OK
  • CD 光盘
  • CHDIR CHDIR
  • COLOR 颜色
  • COPY 复制
  • DATE 日期
  • DEL : Always clears ERRORLEVEL, even if the DEL fails DEL:即使DEL失败,也始终清除ERRORLEVEL
  • DIR DIR
  • ERASE : Always clears ERRORLEVEL, even if ERASE fails 删除:即使ERASE失败,也始终清除ERRORLEVEL
  • MD MD
  • MKDIR MKDIR
  • MKLINK MKLINK
  • MOVE 移动
  • PUSHD PUSHD
  • REN REN
  • RENAME 改名
  • SETLOCAL SETLOCAL
  • TIME 时间
  • TYPE 类型
  • VER VER
  • VERIFY 校验
  • VOL VOL

The next set of commands never clear the ERRORLEVEL to 0 upon success, regardless of context, but instead preserve any existing non-zero value ERRORLEVEL: 成功时,下一组命令永远不会将ERRORLEVEL清除为0,无论上下文如何,而是保留任何现有的非零值ERRORLEVEL:

  • BREAK 打破
  • CLS CLS
  • ECHO 回声
  • ENDLOCAL ENDLOCAL
  • EXIT : Obviously EXIT /B 0 clears the ERRORLEVEL, but EXIT /B without value preserves the prior ERRORLEVEL. EXIT:显然EXIT /B 0清除了ERRORLEVEL,但没有值的EXIT /B保留了先前的ERRORLEVEL。
  • FOR 对于
  • GOTO
  • IF 如果
  • KEYS KEYS
  • PAUSE 暂停
  • POPD POPD
  • RD RD
  • REM REM
  • RMDIR RMDIR
  • SHIFT 转移
  • START 开始
  • TITLE 标题

And then there are these commands that do not clear ERRORLEVEL upon success if issued from the command line or within a script with a .bat extension, but do clear the ERRORLEVEL to 0 if issued from a script with a .cmd extension. 然后,如果从命令行或具有.bat扩展名的脚本中发出,则这些命令在成功时不会清除ERRORLEVEL,但如果从具有.cmd扩展名的脚本发出,则将ERRORLEVEL清除为0。 See https://stackoverflow.com/a/148991/1012053 and https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J for more info. 有关详细信息,请参阅https://stackoverflow.com/a/148991/1012053https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J

  • ASSOC ASSOC
  • DPATH DPATH
  • FTYPE FTYPE
  • PATH 路径
  • PROMPT 提示
  • SET

Regardless of any ERRORLEVEL value, the && operator detects if the prior command was successful, and only executes the subsequent command(s) if it was. 无论任何ERRORLEVEL值如何, &&运算符都会检测先前命令是否成功,并且只执行后续命令(如果是)。 The && operator ignores the value of ERRORLEVEL, and never modifies it. &&运算符忽略ERRORLEVEL的值,并且永远不会修改它。

Here are two examples that show that && always fires if the prior command was successful, even if the ERRORLEVEL is non-zero. 以下两个示例显示,如果先前命令成功,即使ERRORLEVEL非零, &&也会一直触发。 The CD command is an example where the command clears any prior ERRORLEVEL, and the ECHO command is an example where the command does not clear the prior ERRORLEVEL. CD命令是一个示例,其中命令清除任何先前的ERRORLEVEL,并且ECHO命令是命令不清除先前ERRORLEVEL的示例。 Note, I am using (call) to force ERRORLEVEL to 1 before issuing the command that succeeds . 注意,我在发出成功命令之前使用(call)强制ERRORLEVEL为1

C:\TEST>(call)

C:\TEST>echo !errorlevel!
1

C:\test>(call) & cd \test

C:\test>echo !errorlevel!
0

C:\test>(call) & cd \test && echo OK !errorlevel! || echo ERROR !errorlevel!
OK 0

C:\test>(call) & echo Successful command
Successful command

C:\test>echo !errorlevel!
1

C:\test>(call) & echo Successful command && echo OK !errorlevel! || echo ERROR !errorlevel!
Successful command
OK 1

In all of my code examples for error detection, I was relying on the fact that ECHO never clears a previously existing non-zero ERRORLEVEL. 在我的所有错误检测代码示例中,我依赖的事实是ECHO永远不会清除以前存在的非零ERRORLEVEL。 But the script below is an example of what can happen when other commands are used after && or || 但是下面的脚本是在&&||之后使用其他命令时会发生什么的示例 .

@echo off
setlocal enableDelayedExpansion
(call)
echo ERRORLEVEL = !errorlevel!
(call) && echo OK !errorlevel! || echo ERROR !errorlevel!
(call) && (echo OK !errorlevel! & set "err=0") || (echo ERROR !errorlevel! & set "err=1" & echo ERROR !errorlevel!)
echo ERRORLEVEL = !errorlevel!
echo ERR = !ERR!

Here is the output when the script has a .bat extension: 以下是脚本具有.bat扩展名时的输出:

C:\test>test.bat
ERRORLEVEL = 1
ERROR 1
ERROR 1
ERROR 1
ERRORLEVEL = 1
ERR = 1

And here is the output when the script has a .cmd extension: 以下是脚本具有.cmd扩展名时的输出:

C:\test>test.cmd
ERRORLEVEL = 1
ERROR 1
ERROR 1
ERROR 0
ERRORLEVEL = 0
ERR = 1

Remember that every executed command has the potential to alter the ERRORLEVEL. 请记住,每个执行的命令都有可能改变ERRORLEVEL。 So even though && and || 所以即使是&&|| are the most reliable ways to detect command success or failure, one must be careful about what commands are used after those operators if you care about the ERRORLEVEL value. 检测命令成功或失败的最可靠方法是,如果您关心ERRORLEVEL值,必须注意在这些运算符之后使用的命令。

And now it is time to climb out of this stinking rabbit hole and get some fresh air! 而现在是时候爬出这个发臭的兔子洞,并获得一些新鲜空气!

So what have we learned? 所以我们学了什么?

There is no single perfect method to detect whether any arbitrary command was successful or failed. 没有一种完美的方法可以检测任意命令是成功还是失败。 However, && and || 但是, &&|| are the most reliable methods to detect success and failure. 检测成功和失败是最可靠的方法。

In general, neither && nor || 一般来说,既不是&&也不是|| modify the ERRORLEVEL directly. 直接修改ERRORLEVEL。 But there are a few rare exceptions. 但是有一些罕见的例外。

  • || properly sets the ERRORLEVEL that would otherwise be missed when RD or redirection fails 正确设置ERRORLEVEL,否则在RD或重定向失败时会错过
  • || sets a different ERRORLEVEL upon failed execution of an invalid command then would occur if || 在执行无效命令失败时设置不同的ERRORLEVEL,如果||则会发生 were not used (1 vs. 9009). 未使用(1对9009)。

Finally, || 最后, || does not detect a non-zero ERRORLEVEL returned by a batch script as an error unless the CALL command was used. 除非使用了CALL命令,否则不会将批处理脚本返回的非零ERRORLEVEL检测为错误。

If you rely strictly on if errorlevel 1 ... or if %errorlevel% neq 0 ... to detect errors, then you run the risk of missing errors that RD and redirection (and others?) might throw, and you also run the risk of mistakenly thinking certain internal commands failed when in reality it could be a holdover from a prior command that failed. 如果你严格依赖于if errorlevel 1 ...或者if %errorlevel% neq 0 ...来检测错误,那么你冒着丢失RD和重定向(以及其他?)可能抛出的错误的风险,你也运行错误地认为某些内部命令失败的风险实际上它可能是先前失败的命令的保留。

To build a solution for batch files to set the return code while using goto :eof you can change your script a bit. 要构建批处理文件的解决方案,以便在使用goto :eof时设置返回代码,您可以稍微更改脚本。

mkdir \\\failure || goto :EXIT
echo Only on Success
exit /b

:exit
(call)

Now you can use 现在你可以使用了

test.bat || echo Failed

The only drawback here is the loss of the errorlevel. 这里唯一的缺点是错误级别的丢失。
In this case the return code is set to false but the errorlevel is always set to 1 , by the invalid (call) 在这种情况下,返回代码设置为falsefalse级别始终设置为1 ,由无效(call)
Currently I can't found any possible way to set both, the errorlevel and the return code to user defined values 目前我找不到任何可能的方法来设置错误级别和返回代码到用户定义的值

The true Errorlevel doesn't survive the double pipe (on failure) operator. 真正的Errorlevel不会在双管道(失败时)运算符中存在。

Use logic instead. 请改用逻辑。 For example, below is one way you could do it: 例如,下面是您可以执行此操作的一种方法:

mkdir \\PC01\c$\Test
if "%errorlevel%" == "0" (
echo success
) else (
echo failure
)

edit: 编辑:

If the command that precedes this is not a single command then more has to be done to track errorlevel. 如果此前的命令不是单个命令,则必须执行更多操作来跟踪errorlevel。 Example if you call a script, then in that script you have to manage the passing of errorlevel back to this code. 例如,如果您调用脚本,那么在该脚本中您必须管理将errorlevel传递回此代码。

edit 2: 编辑2:

Here are test scenarios where the ERRORLEVEL should be '9009' and their output. 以下是ERRORLEVEL应为'9009'的测试场景及其输出。

1) No failure piping, uses if logic. 1)没有管道故障,如果是逻辑则使用。

setlocal enableDelayedExpansion
mybad.exe 
if "!errorlevel!" == "0" (
echo success !errorlevel!
) else (
echo Errorlevel is now !errorlevel!
echo Errorlevel is now !errorlevel!
)

'mybad.exe' is not recognized as an internal or external command, operable program or batch file. 'mybad.exe'无法识别为内部或外部命令,可运行程序或批处理文件。

Errorlevel is now 9009 Errorlevel现在是9009

Errorlevel is now 9009 Errorlevel现在是9009

2) Failure piping, echo 2)管道故障,回声

setlocal enableDelayedExpansion
mybad.exe || echo Errorlevel is now !errorlevel!
echo Errorlevel is now !errorlevel!

'mybad.exe' is not recognized as an internal or external command, operable program or batch file. 'mybad.exe'无法识别为内部或外部命令,可运行程序或批处理文件。

Errorlevel is now 1 Errorlevel现在是1

Errorlevel is now 1 Errorlevel现在是1

3) Failure piping, goto 3)管道故障,转到

setlocal enableDelayedExpansion
mybad.exe || goto :fail
exit
:fail
echo Errorlevel is now !errorlevel!

'mybad.exe' is not recognized as an internal or external command, operable program or batch file. 'mybad.exe'无法识别为内部或外部命令,可运行程序或批处理文件。

Errorlevel is now 1 Errorlevel现在是1

So if all you care about is "Something" failed, then OK. 所以,如果你关心的是“Something”失败,那么好的。 Code 1 is as good as anything else. 代码1和其他任何东西一样好。 But if you need to know "what" failed, then you can't just failure pipe and let it wipe out the actual result. 但是如果你需要知道“什么”失败了,那么你不能只是失败管道并让它消灭实际结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM