2012-06-23 46 views

回答

22

你可能认为你可以做类似下面的事情,但它不会工作。

(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= 
+0

简单的解决方案打破了使用三通(同时输出)的主要原因。对于第一种解决方案,您可以使用“set/p MY_ERROR =

+0

“call set”,“call echo”等是什么处理?我从来没有见过这种语法。 – alecov

+1

@Alek - 在初始解析后获得第二轮变量扩展是一种老式的攻击。这是使用延迟扩展的替代方法。 'echo!var!'类似于'call echo %% var %%'。延迟扩展通常是首选,但有时需要CALL破解。 – dbenham