Batch file 退出/b在具有其他命令的块内时无法正常工作

Batch file 退出/b在具有其他命令的块内时无法正常工作,batch-file,cmd,windows-7,Batch File,Cmd,Windows 7,我有一个批处理文件,它需要在32位上下文中运行,因此包含一段代码,用于使用自己的路径调用32位命令处理器。此脚本还需要能够在发生故障时返回错误代码,这是通过退出/b 123执行的。然而… 当退出位于()块中,并且包含其后的任何语句时,将无法正确返回该语句 @echo off setlocal EnableDelayedExpansion rem Ensure we're running in 32-bit mode if not %PROCESSOR_ARCHITECTURE%==x86 (

我有一个批处理文件,它需要在32位上下文中运行,因此包含一段代码,用于使用自己的路径调用32位命令处理器。此脚本还需要能够在发生故障时返回错误代码,这是通过
退出/b 123执行的。然而…
退出
位于
块中,并且包含其后的任何语句时,将无法正确返回该语句

@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
before

H:\>echo %ERRORLEVEL%
456

H:\>
结果如下:

H:\>sub.bat
Thunking to 32-bit mode
before
0

H:\>
如果在退出
后删除
回显
,则它将完全按照预期工作

H:\>sub.bat
Thunking to 32-bit mode
before
456

H:\>
即使用
rem
或任何其他命令替换
echo
,它仍然会失败。如果手动运行32位
cmd.exe
并运行相同的脚本,则会正确设置退出代码

@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
before

H:\>echo %ERRORLEVEL%
456

H:\>

有人能对此给出解释和解决方法吗?

在脚本的“else”部分使用/b开关会导致cmd.exe的第二个实例丢失退出代码

当批处理文件的第二个实例从Syswow64执行时,它将以代码456退出。其父cmd.exe将收到此退出代码,但无意保留它。cmd.exe能够成功运行批处理,因此以0退出,返回到第一个实例

如果在脚本的“else”部分省略/b开关,这将强制批处理文件退出其父cmd.exe,而不仅仅是完成处理。由于随后命令cmd.exe使用456退出代码退出,因此将保留该代码


“退出”的帮助文本确实推断出了这种行为,但在您阅读时牢记这一点之前,它似乎并不十分明显

当从后者中删除
/b
退出
起作用,它还有其他影响,如直接从32位运行时退出命令提示符,以及任何调用批处理脚本。另外,第二个块通常需要更多的代码,并且有自己的条件,但是在本例中被去掉了。@Deanna-既然如此,为什么不在SysWOW调用中传递一个参数(
%Windir%\SysWOW64\cmd.exe/c%0/B
)。然后在“else”条件下使用:
退出%1 456
。如果没有递归调用,
%1
将为空:
退出456
。非常好的解释+1(这是您在本论坛的第一个答案)欢迎
:)
@Jason,搞错了,我们需要的是/B,当它不是递归调用时,而不是当它是递归调用时。不过还是很容易做到。为了获得最大的灵活性,环境变量可能比参数更可取。我个人建议,不管当前命令处理器的位是多少,批处理文件总是在子进程中自行运行。(你可以设置一个参数或一个环境变量来防止无限递归。)你说的是一个
else
部分,但我在问题中找不到任何
else
关键字…
%Windir%\SysWOW64\cmd.exe/c%0^&exit%%%errorlevel%%
也应该有效(我对Adam答案的评论的附录)。