如何在Windows批处理编程中获取pipe道中命令的错误级别?

batch file默认返回最后一个命令的错误代码。

是否有可能返回以前的命令的错误代码。 最值得注意的是,是否可以返回pipe道中命令的错误代码?

例如,这个一行批处理脚本

foo.exe 

返回foo的错误代码。 但是这个:

 foo.exe | tee output.txt 

总是返回T的退出代码,这是零。

一种解决方法是通过文件进行间接寻址。

喜欢这个

 foo.exe > tmp.txt set FOOERR=%ERRORLEVEL% cat tmp.txt exit %FOOERR% 

我有一个类似的问题,解决了以下解决方案,因为我不需要检测确切的错误代码,只是成功或失败。

 echo > .failed.tmp ( foo.exe && del .failed.tmp ) | tee foo.log if exist .failed.tmp ( del .failed.tmp exit /b 1 ) else ( exit /b 0 ) 

管道命令运行之前,%ERRORLEVEL%变量不会被更新; 你必须使用其他答案中建议的包装。

但是,您可以使用“IF ERRORLEVEL#”。 例如:

 ( type filename @REM Use an existing (or not) filename to test each branch IF ERRORLEVEL 1 (echo ERROR) ELSE (echo OKAY) ) > logfile.txt 

只有返回错误时,ECHO才会运行。 但%ERRORLEVEL%似乎不一致。

编辑:更改示例为可运行的。

大约一天的挖掘之后,我找到了一个办法:

 set error_=0 9>&1 1>&2 2>&9 (for /f "delims=" %%i in ('9^>^&1 1^>^&2 2^>^&9 ^(^(^(2^>^&1 call "%homeDir%%1"^) ^|^| ^(1^>^&2 2^>nul echo FAILED^)^) ^| 2^>nul "%homeDir%mtee" /T /+ "%homeDir%logs\%date_%_%1.log"^)') do (set error_=1)) exit /b %error_% 

在上面的例子中,“%homeDir %% 1”正在执行,其输出被传送到“%homeDir%mtee”。 这一行检测失败(我建议你绘制一个批处理上下文和stdin /标准输出/ stderr分配的图表,以了解它是什么:-))。 我没有找到提取实际错误级别的好方法。 我得到的最好的东西是用一些批处理脚本调用'call rc.bat'替换'echo'命令,它看起来像:

 @echo %errorlevel% 

然后用'set error _ = %% i'替换'set error_ = 1'。

但问题是,这个调用可能会失败,而且不容易检测到。 尽管如此,它总比没有好 – 我在互联网上没有找到任何解决方案。

你可以通过在你的命令文件中创建一个包装来解决这个问题:

 rem wrapper for command file, wrapper.cmd call foo.exe echo %errorlevel% if errorlevel 1 goto... 

然后将三通附加到包装上:

 wrapper.cmd | tee result.log 

当然这并不完全一样,例如,如果你想在包装文件中登录几个文件,这是不可能的,但在我的情况下,它解决了这个问题。

要调用输入bat-file,而不是单个命令,并自由地使用errorlevel,我使用这样的技巧:

 if "%1" == "body" goto :body call %0 body | tee log.txt goto :eof :body set nls_lang=american_america set HomePath=%~dp0 sqlplus "usr/pwd@tnsname" "@%HomePath%script.sql" if errorlevel 1 goto dberror rem Here I can do something which is dependent on correct finish of script.sql :dberror echo script.sqlerror failed 

它使用tee从批量调用任何命令分离。