The commands within a FOR IN() clause are run in a brand new CMD.EXE session, so it is impossible to directly access the ERRORLEVEL or any environment variable that the command(s) may set.
Normally the best and simplest solution is to use a temporary file:
yourCommand >output.txt
set exit_code=%errorlevel%
for /f "delims=" %%i in (output.txt) do processOutput
del output.txt
But you have stated that you cannot use temporary files.
The only option is to echo the ERRORLEVEL within the IN() clause and then parse the ERRORLEVEL within the DO clause. Echoing the ERRORLEVEL is a bit tricky because %ERRORLEVEL% is expanded at parse time, and the entire IN() clause is parsed at once, so %ERRORLEVEL% will always be 0.
The IN() clause commands are executed with a command line context, not a batch context. The new CMD.EXE session does not inherit the current delayed expansion state - it defaults to delayed expansion disabled. The simplest solution is to use CALL along with a properly escaped %ERRORLEVEL% to delay the expansion until after your command has executed. A caret is added to escape for the command context. Then the percents and caret are doubled to escape for the parent batch - %%^^ERRORLEVEL%%.
You will want to make your ERRORLEVEL message unique so that your DO clause can distinguish the ERRORLEVEL from normal output.
@echo off
setlocal enableDelayedExpansion
for /f "delims=" %%A in ('dir DoesNotExist^&call echo ::ERROR::%%^^ERRORLEVEL%%') do (
set "ln=%%A"
if "!ln:~0,9!" equ "::ERROR::" (
set "EXIT_CODE=!LN:~9!"
) else (
REM normal output - do whatever
echo %%A
)
)
echo EXIT_CODE=%EXIT_CODE%
Here is some sample output of the above
C:\test>test.bat
File Not Found
Volume in drive C is OS
Volume Serial Number is EE2C-5A11
Directory of C:\test
EXIT_CODE=1
windbg,disassemblingandollydbgtags from this question. - Mike Kwan