捕获命令的输出并检查批处理脚本中的错误级别

时间:2015-01-20 02:01:46

标签: windows batch-file error-handling

我有一个命令(让我们称之为command)打印到标准输出,并且还会根据执行的成功或失败设置ERRORLEVEL。我想从将处理command输出的批处理脚本中调用command,但仅当command以ERRORLEVEL为0(即成功)退出时。这样做最好不需要临时文件或检查命令的输出来推断它是否成功。

我能够使用for语句捕获命令的输出,但是在执行此操作时我无法检查ERRORLEVEL。我尝试过类似的东西:

for /F %%A in ('command') do (
     REM The following check does not seem to work
     if ERRORLEVEL 1 goto error
     REM otherwise, do stuff with %%A
)

我也尝试过使用%errorlevel%!errorlevel!(使用setlocal enabledelayedexpansion),但都没有效果。

2 个答案:

答案 0 :(得分:1)

使用如下代码:

@echo off
"command.exe">"%TEMP%\CommandOutput.tmp"
if errorlevel 1 goto Failed

for /F "usebackq" %%A in ("%TEMP%\CommandOutput.tmp") do (
     REM Do stuff with %%A
     echo %%A
)
goto DelTempFile

:Failed
echo There was an error on executing command.

:DelTempFile
if exist "%TEMP%\CommandOutput.tmp" del "%TEMP%\CommandOutput.tmp"

此批处理代码首先运行命令,将标准输出重定向到临时文件的文件夹中的文件。接下来,它会评估命令的退出代码。

如果没有错误,则使用 处理输出。

错误会显示相应的错误消息。

最后,在批处理终止之前删除带有捕获输出的临时文件。

答案 1 :(得分:0)

问题是在in命令的for子句中执行的命令在单独的cmd实例中运行,并且该实例的退出代码不会传播到代码在do子句中。

如果您需要for命令来处理输出,并且需要errorlevel子句中的spawned命令的do,则需要将两者分开并生成临时文件。

Mofi的答案可能是最快,最简单,更直接的解决方案,无需涉及外部脚本引擎/ powershell。

对于大多数代码包含在in子句中的解决方案:

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Some commands for testing - command/uncomment as needed
    set "command=findstr 2> nul"  
    rem set "command=ping -n 1 localhost"
    rem set "command=ping -n 1 localhost | find "TTL^^^=" "

    set "el="
    for /f "delims=" %%a in ('
        cmd /v /q /c "set "t^=%temp%\%~nx0.%random%"&(>"!t!" (%command%)&echo(!errorlevel!&type "!t!"&del /q "!t!")"
    ') do if not defined el ( 
        rem The first line in the output is the exit code of the executed command
        set "el=%%a" & if %%a gtr 0 goto failed 
    ) else (
        rem Process the output of the command
        echo(%%a
    ) 
    exit /b

:failed
    echo failed with errorlevel %el%
    goto :eof

基本思路是将errorlevel作为执行命令输出的第一行,这样我们就可以检查它并决定是否需要更多处理。

注意:这不会避免必须将所有输出加载到内存中。 for /f在开始执行do子句中的代码之前加载所有数据,并且在从命令执行的文件中检索数据时效率更高(其中一个原因是来自Mofi的答案更快)