0

我正在尝试使用 Windows 批处理文件来运行命令,将其输出通过管道传输到另一个命令,并捕获第一个命令的退出状态。但显然,我不能这样做,尽管我承认 Windows 批处理文件是如此神秘,以至于我可能错过了一项技术。 如何捕获命令的退出状态并通过管道传输其输出?

这是经典do_a_thing | tee logfile.txt用法,但我希望能够检查是否do_a_thing成功。经过大量的鬼混、谷歌搜索和阅读 StackOverflow,我想出了以下内容:

setlocal enabledelayedexpansion
set rc=-1
( false & set rc=!errorlevel! & echo rc=!rc! ) | tee logfile.txt
echo %rc%

我曾希望会产生:

C:\>test.bat 
C:\>setlocal enabledelayedexpansion 
C:\>set rc=-1 
C:\>(false & set rc=!errorlevel!   & echo rc=!rc!  ) | tee logfile.txt
rc=1 
C:\>echo 1
1

但是,唉,它没有:

C:\>test.bat
C:\>setlocal enabledelayedexpansion
C:\>set rc=-1
C:\>(false & set rc=!errorlevel! & echo rc=!rc! ) | tee logfile.txt
rc=!rc!
C:\>echo -1
-1

删除“ | tee logfile.txt”会产生 的预期值!rc!,但当然,它不会让我捕获日志文件。

C:\>test.bat
C:\>setlocal enabledelayedexpansion
C:\>set rc=-1
C:\>(false & set rc=!errorlevel! & echo rc=!rc! )
rc=1
C:\>echo 1
1
4

1 回答 1

2

您尝试执行的操作不起作用,因为管道的每一侧都在其自己的命令行上下文中的命令 shell 中执行,默认情况下延迟扩展关闭。请参阅为什么在管道代码块中延迟扩展失败?了解更多信息。接受的答案解释了一切,其他答案有助于为接受的答案提供上下文。

最简单的解决方案是将错误代码写入临时文件,然后在命令完成后将该文件读入变量。

( false & call echo %%^^errorlevel%%>returnCode.txt ) | tee logfile.txt
set "rc="
<returnCode.txt set /p "rc="
del returnCode.txt
echo rc=%rc%

CALL 语句提供在命令运行后发生的另一个级别的解析。诀窍是延迟扩展 OF %errorlevel% 直到您正在测试的命令运行之后。在命令上下文中,您可以简单地使用CALL ECHO %^ERRORLEVEL%. 但是命令行在到达命令上下文之前还必须通过批处理上下文解析,因此百分比必须转义为%%,插入符号转义为^^.

于 2012-11-12T17:43:12.113 回答