在下面提供的示例中,我执行nmake,然后将STDOUT/STDERR重定向到tee,然后将它发送到屏幕以及日志文件。 问题是,我试图捕获nmake的退出码而不是tee。 我需要的是nmake的退出代码,而不是三通。Windows命令解释器:如何获得第一个管道命令的退出代码
nmake | tee output.txt
在下面提供的示例中,我执行nmake,然后将STDOUT/STDERR重定向到tee,然后将它发送到屏幕以及日志文件。 问题是,我试图捕获nmake的退出码而不是tee。 我需要的是nmake的退出代码,而不是三通。Windows命令解释器:如何获得第一个管道命令的退出代码
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
或者你也可以嵌入ERRORLEVEL在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管道时存在许多微妙的复杂情况。一个很好的参考是Why does delayed expansion fail when inside a piped block of code?。我建议阅读这个问题和所有的答案。所选答案有最佳信息,但其他答案有助于提供上下文。
EDIT 2015年6月2日
我最近发现可以使用DOSKEY宏干净商店,并通过管道,无论(或两者)双方检索错误级别,而不诉诸临时文件。我从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
如果你愿意,你可以在最后添加一个命令来清除Err“宏”的定义您检索后值。
doskey /exename=err err=
简单的解决方案打破了使用三通(同时输出)的主要原因。对于第一种解决方案,您可以使用“set/p MY_ERROR =
“call set”,“call echo”等是什么处理?我从来没有见过这种语法。 – alecov
@Alek - 在初始解析后获得第二轮变量扩展是一种老式的攻击。这是使用延迟扩展的替代方法。 'echo!var!'类似于'call echo %% var %%'。延迟扩展通常是首选,但有时需要CALL破解。 – dbenham