Windows命令解释器:如何获取第一个管道命令的退出代码

dob*_*ler 17 windows cmd pipe exit-code

在下面提供的示例中,我执行nmake然后将STDOUT/STDERR重定向到tee,然后将其发送到屏幕,还发送到日志文件.问题是我正在尝试捕获nmake的退出代码而不是tee.我需要的是nmake的退出代码,而不是tee.

nmake | tee output.txt
Run Code Online (Sandbox Code Playgroud)

dbe*_*ham 27

您可能认为您可以执行以下操作,但它不起作用.

(nmake & call set myError=%%errorlevel%%) | tee output.txt
Run Code Online (Sandbox Code Playgroud)

问题在于Windows管道的工作机制.管道的每一侧都在它自己的CMD外壳中执行.因此,在命令完成后,您在此处设置的任何环境变量都将消失.也%ERRORLEVEL%的延迟扩展是更加复杂,因为解析的额外水平,并且由于CMD壳具有命令行上下文,而不是分批上下文.

你可以这样做:

(nmake & call echo %%^^errorlevel%% ^>myError.txt) | tee output.txt
for /f %%A in (myError.txt) do echo nmake returned %%A
del myError.txt
Run Code Online (Sandbox Code Playgroud)

或者您可以在output.txt中嵌入errorlevel:

(nmake & call echo nmakeReturnCode: %%^^errorlevel%%) | tee output.txt
for /f "tokens=2" %%A in ('findstr /b "nmakeReturnCode:" output.txt') do echo nmake returned %%A
Run Code Online (Sandbox Code Playgroud)

但最简单的解决方案似乎是

nmake >output.txt
set myError=%errorlevel%
type output.txt
echo nmake returned %myError%
Run Code Online (Sandbox Code Playgroud)


注意 - 使用Windows管道时会有许多细微的复杂情况.一个很好的参考是为什么在管道代码块内部延迟扩展会失败?.我建议阅读问题和所有答案.所选答案具有最佳信息,但其他答案有助于提供上下文.

编辑2015-06-02

我最近发现你可以使用DOSKEY宏从管道的任一侧(或两侧)干净地存储和检索ERRORLEVEL,而不需要使用临时文件.我从DosTips用户埃德Dyreen的想法http://www.dostips.com/forum/viewtopic.php?p=41409#p41409.DOSKEY宏不能通过批处理执行,但是在ENDLOCAL和CMD/C退出后,定义仍然存在!

以下是在您的情况下如何使用它:

(nmake & call doskey /exename=err err=%%^^errorlevel%%) | tee output.txt
for /f "tokens=2 delims==" %%A in ('doskey /m:err') do echo nmake returned %%A
Run Code Online (Sandbox Code Playgroud)

如果需要,可以在结束时再添加一个命令,以便在检索到值后清除错误"宏"的定义.

doskey /exename=err err=
Run Code Online (Sandbox Code Playgroud)

  • @Alek - 在初始解析后进行第二轮变量扩展是一种古老的技巧。它是使用延迟扩展的替代方法。`echo !var!` 类似于 `call echo %%var%%`。延迟扩展通常是首选,但有时需要 CALL hack。 (2认同)