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

在下面提供的示例中,我执行nmake,然后将STDOUT / STDERRredirect到tee,然后将它发送到屏幕以及日志文件。 问题是,我试图捕获nmake退出代码,而不是三通。 我需要的是从nmake退出代码,而不是三通。

nmake | tee output.txt 

你可能会认为你可以做类似下面的事情,但是不行。

 (nmake & call set myError=%%errorlevel%%) | tee output.txt 

问题在于Windows管道工作的机制。 管道的每一侧都在它自己的CMD外壳中执行。 所以一旦命令完成,你设置的任何环境变量都会消失。 此外,由于额外的解析级别,%errorlevel%的延迟扩展更为复杂,并且由于CMD shell具有命令行上下文,而不是批处理上下文。

你可以做这样的事情:

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

或者你可以在output.txt中嵌入错误级别:

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

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

 nmake >output.txt set myError=%errorlevel% type output.txt echo nmake returned %myError% 

注意 – 使用Windows管道时有许多微妙的复杂性。 一个很好的参考是为什么在一个管道代码块中延迟扩展失败? 我建议阅读这个问题和所有的答案。 所选的答案有最好的信息,但其他答案有助于提供上下文。

编辑2015-06-02

我最近发现你可以使用DOSKEY宏来干净地存储和从管道的任何一端(或两端)检索ERRORLEVEL,而不需要临时文件。 我从DosTips用户Ed 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 

如果你愿意,你可以在最后添加一个命令来清除错误“宏”的定义后,你已经检索的价值。

 doskey /exename=err err=