在带有其他命令的块内时退出 /b 无法正常工作
Posted
技术标签:
【中文标题】在带有其他命令的块内时退出 /b 无法正常工作【英文标题】:exit /b not working correctly when inside a block with other commands 【发布时间】:2016-03-17 13:39:20 【问题描述】:我有一个需要在 32 位上下文中运行的批处理文件,因此包含一些代码以使用自己的路径调用 32 位命令处理器。该脚本还需要能够在失败时返回错误代码,它通过exit /b 123
执行。但是...
当 exit
位于 (
)
块中时,并且在其后包含任何语句,则不会正确返回。
@echo off
setlocal EnableDelayedExpansion
rem Ensure we're running in 32-bit mode
if not %PROCESSOR_ARCHITECTURE%==x86 (
echo Thunking to 32-bit mode
%Windir%\SysWOW64\cmd.exe /c %0
echo !ERRORLEVEL!
exit /b !ERRORLEVEL!
)
(
echo before
exit /b 456
echo after
)
输出如下:
H:\>sub.bat
Thunking to 32-bit mode
before
0
H:\>
如果您在exit
之后删除echo
,那么它的工作方式与预期完全一样。
H:\>sub.bat
Thunking to 32-bit mode
before
456
H:\>
即使您将echo
替换为rem
或任何其他命令,它仍然会失败。如果您手动运行 32 位 cmd.exe
并运行相同的脚本,则退出代码设置正确。
H:\>sub.bat
before
H:\>echo %ERRORLEVEL%
456
H:\>
谁能对此给出解释和解决方法?
【问题讨论】:
%Windir%\SysWOW64\cmd.exe /c %0 ^& exit %%%%errorlevel%%%%
应该也可以工作(我对亚当回答的评论的附录)。
【参考方案1】:
在脚本的“else”部分使用 /b 开关导致退出代码被 cmd.exe 的第二个实例丢失。
当批处理文件的第二个实例从 Syswow64 执行时,它将以代码 456 退出。其父 cmd.exe 将收到此退出代码,但没有兴趣保留它。 cmd.exe 能够成功运行批处理,因此以 0 退出,返回到第一个实例。
如果您在脚本的“else”部分省略 /b 开关,这将强制批处理文件退出其父 cmd.exe,而不仅仅是完成处理。由于 cmd.exe 然后被告知以 456 退出代码退出,这将被保留。
“exit”的帮助文本确实可以推断出这种行为,但在您牢记这一点之前,它似乎并不十分明显!
【讨论】:
虽然从后者exit
中删除 /b
是可行的,但它还有其他影响,例如如果直接从 32 位运行退出命令提示符,以及任何调用批处理脚本。此外,第二个块通常在更多代码之后并且有自己的条件,但在本示例中被剥离。
@Deanna - 既然如此,为什么不在您的 SysWOW 调用 (%Windir%\SysWOW64\cmd.exe /c %0 /B
) 中传递一个参数。然后在您的“其他”条件下使用:exit %1 456
。如果没有递归调用,%1
将为空:exit 456
。
很好的解释! +1(这是您在此论坛的第一个答案)欢迎! :)
@Jason,错误的方式,我们需要 /B 当它不是递归调用而不是当它是。尽管如此,仍然很容易完成。环境变量可能比参数更可取,以获得最大的灵活性。就个人而言,我建议批处理文件 always 在子进程中运行,而不管当前命令处理器的位数如何。 (您可以设置参数或环境变量来防止无限递归。)
您说的是else
部分,但我在问题中找不到任何else
关键字...以上是关于在带有其他命令的块内时退出 /b 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章