这是一个蝙蝠脚本:
@ECHO OFF REM how to get the sub process's exit code SETLOCAL ENABLEDELAYEDEXPANSION FOR /F "usebackq tokens=* delims=" %%i IN ( `^ tracert google.com ^ ^& EXIT /B 5 ^ ` ) DO ( ECHO [log] %%i ) REM What i need here is "EXIT_CODE:5" , REM but, "EXIT_CODE:0" displayed, help ! REM REM ***NOTE***: no temporary file or any none-bat style support, REM an exact way is welcome, here is bat-zone only. REM ECHO EXIT_CODE:%ERRORLEVEL% ENDLOCAL PAUSE
我需要捕获子进程的输出和退出代码,之后我在for...in
语句中处理输出。但是退出代码没有通过:
当子进程退出时,退出代码或者在for...in
语句完成后由主进程刷新,或者它可能从未在第一时间传递。
答案 0 :(得分:3)
FOR IN()子句中的命令在全新的CMD.EXE会话中运行,因此无法直接访问ERRORLEVEL或命令可能设置的任何环境变量。
通常,最好和最简单的解决方案是使用临时文件:
yourCommand >output.txt
set exit_code=%errorlevel%
for /f "delims=" %%i in (output.txt) do processOutput
del output.txt
但您已声明不能使用临时文件。
唯一的选择是在IN()子句中回显ERRORLEVEL,然后解析DO子句中的ERRORLEVEL。回调ERRORLEVEL有点棘手,因为%ERRORLEVEL%在分析时扩展,并且整个IN()子句一次被解析,因此%ERRORLEVEL%将始终为0。
IN()子句命令使用命令行上下文执行,而不是批处理上下文。新的CMD.EXE会话不会继承当前的延迟扩展状态 - 它默认为禁用延迟扩展。最简单的解决方案是使用CALL和正确转义的%ERRORLEVEL%
来延迟扩展,直到命令执行完毕。添加了一个插入符以转义命令上下文。然后将百分比和插入符号翻倍以换取父批次 - %%^^ERRORLEVEL%%
。
您需要使您的ERRORLEVEL消息唯一,以便您的DO子句可以区分ERRORLEVEL和正常输出。
@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%
以上是
的一些示例输出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
答案 1 :(得分:1)
可以通过%ERRORLEVEL%
读取程序的退出代码。稍后将其分配给变量echo
:
set exitstatus=%ERRORLEVEL%
echo %exitstatus%
你可能会发现Raymond Chen的this article很有意思。