如何获取子流程的退出代码?

时间:2012-10-10 13:36:00

标签: windows cmd

这是一个蝙蝠脚本:

@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语句完成后由主进程刷新,或者它可能从未在第一时间传递。

2 个答案:

答案 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很有意思。

相关问题