views:

1402

answers:

4

Batch files return the error code of the last command by default.

Is it somehow possible to return the error code of a former command. Most notably is it possible to return the error code of a command in a pipe?

For example, this one-line batch script

foo.exe

returns the error code of foo. But this one:

foo.exe | tee output.txt

always returns the exit code of tee, which is zero.

A: 

I don't rightly know, but I've found this site very helpful for all batch related stuff in the past: http://www.ss64.com/nt/

corlettk
+5  A: 

One workaround is to make an indirection through a file.

Like this

foo.exe > tmp.txt
set FOOERR=%ERRORLEVEL%
cat tmp.txt
exit %FOOERR%
+2  A: 

After ~1 day of digging I found a way to do that:

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_%

In the example above "%homeDir%%1" is being executed and it's output is piped to "%homeDir%mtee". This line detects failures (I'd suggest you to draw a diagram of batch contexts and their stdin/stdout/stderr assignments in order to understand what it does :-) ). I did not find a good way to extract actual errorlevel -- best thing I've got was to replace 'echo' command with some batch script call 'call rc.bat' which look like:

@echo %errorlevel%

and then replace 'set error_=1' with 'set error_=%%i'.

But the problem is that this call may fail too and it is not easy to detect that. Still it is much better than nothing -- I did not find any solution for that in i-net.

crusader
A: 

You can solve the problem by creating a wrapper around your command file:

rem wrapper for command file, wrapper.cmd

call foo.exe

echo %errorlevel%

if errorlevel 1 goto...

Then append tee to the wrapper:

wrapper.cmd | tee result.log

Of course this does not exactly the same, e.g. if you want to log in several files in the wrapped file, it is not possible, but in my case it solved the problem.

Fritz