如何捕获子批处理文件的返回错误级别并进行相应处理

时间:2019-04-02 20:37:56

标签: batch-file errorlevel

我正在处理一个调用其他4个批处理文件的批处理文件。如果子批处理文件返回的错误级别代码不是0,则我希望父批处理文件捕获它,发送电子邮件并退出父批处理文件。但是,一旦第一个子批处理文件被调用并以非零错误级别返回,则父批处理文件中的任何后续命令都不会运行。这是我的批处理代码:

rem ** setup so it logs itself **
set parent=%~dp0
set me=%~n0
set LOGFILE=%parent%logs\%me%.log 2>&1
if exist "%LOGFILE%" del %LOGFILE% /f /s /q
call :LOG > %LOGFILE%
exit

:LOG
@ECHO OFF
SETLOCAL ENABLEEXTENSIONS EnableDelayedExpansion

echo ParentDir: %parent%
echo ProgramName: %me%
echo.

rem ** script variables **

set batFile1=%parent%FILE1.bat
set batFile2=%parent%FILE2.bat
set batFile3=%parent%FILE3.bat
set batFile4=%parent%FILE4.bat

set FromEmail=server@domain.com
set Recipient=adminuser@domain.com
set CCRecipient= 

set Subject=Email Subject
set Message=There was an error in running nightly batch files. Please look at the logs to determine which batch file is causing a problem. \n\nAt your service\nAdmin

set Server=smtp.domain.com
set Port=25


rem ** run bat files and capture error message **

echo.
echo Start: Send Email
set Message=Debug test code
c:\APPS\sendemail.exe -f %FromEmail% -t %Recipient% -cc %CCRecipient% -u "%Subject%" -m "%Message%" -v -s %Server%

call %batFile1%

set exitcode=%ERRORLEVEL%

echo %exitcode%

echo.
echo Start: Send Email
set Message=Debug test code !exitcode!
c:\APPS\sendemail.exe -f %FromEmail% -t %Recipient% -cc %CCRecipient% -u "%Subject%" -m "%Message%" -v -s %Server%

if %exitcode% NEQ 0 (

        echo.
        set Message=Execution of !batFile1! failed with error message !errorcode!. Examine the logs and fix any issues before next run.\n\nAt your service\nAdmin
        echo Start: Send Email
        c:\APPS\sendemail.exe -f !FromEmail! -t !Recipient! -cc !CCRecipient! -u "!Subject!" -m "!Message!" -v -s !Server!

        rem ** force execution to quit if check fails
        EXIT /B %ERRORLEVEL%
)

call %batFile2%

if %ERRORLEVEL% NEQ 0 (

        echo.
        set Message=Execution of %batFile2% failed with error message %ERRORLEVEL%. Examine the logs and fix any issues before next run.\n\nAt your service\nAdmin
        echo Start: Send Email
        c:\APPS\sendemail.exe -f %FromEmail% -t %Recipient% -cc %CCRecipient% -u "%Subject%" -m "%Message%" -v -s %Server%

        rem ** force execution to quit if check fails
        EXIT /B %ERRORLEVEL%
)

call %batFile3%

if %ERRORLEVEL% NEQ 0 (

        echo.
        set Message=Execution of %batFile3% failed with error message %ERRORLEVEL%. Examine the logs and fix any issues before next run.\n\nAt your service\nAdmin
        echo Start: Send Email
        c:\APPS\sendemail.exe -f %FromEmail% -t %Recipient% -cc %CCRecipient% -u "%Subject%" -m "%Message%" -v -s %Server%

        rem ** force execution to quit if check fails
        EXIT /B %ERRORLEVEL%
)

call %batFile4%

if %ERRORLEVEL% NEQ 0 (

        echo.
        set Message=Execution of %batFile4% failed with error message %ERRORLEVEL%. Examine the logs and fix any issues before next run.\n\nAt your service\nAdmin
        echo Start: Send Email
        c:\APPS\sendemail.exe -f %FromEmail% -t %Recipient% -cc %CCRecipient% -u "%Subject%" -m "%Message%" -v -s %Server%

        rem ** force execution to quit if check fails
        EXIT /B %ERRORLEVEL%
)


EXIT /B %ERRORLEVEL%

似乎没有执行任何跟随命令call %batFile1%

的代码行

出于参考目的,这是%batFile1%退出的方式:

EXIT /B 254

,因此每次应返回%ERRORLEVEL%254。在致电batFile1之前发送的测试电子邮件效果很好。

1 个答案:

答案 0 :(得分:0)

@echo off
setlocal EnableExtensions

rem ** setup so it logs itself **

set "parent=%~dp0"
set "me=%~n0"
set "LOGFILE=%parent%logs\%me%.log"
if exist "%LOGFILE%" del "%LOGFILE%" /f /s /q
call :LOG > "%LOGFILE%" 2>&1
exit


:LOG
setlocal

echo ParentDir: %parent%
echo ProgramName: %me%
echo.

rem ** script variables **

set batFiles="%parent%FILE1.bat" "%parent%FILE2.bat" "%parent%FILE3.bat" "%parent%FILE4.bat"

set "FromEmail=server@domain.com"
set "Recipient=adminuser@domain.com"
set "CCRecipient="

set "Subject=Email Subject"
set Message=There was an error in running nightly batch files.^
 Please look at the logs to determine which batch file is causing a problem.\n\n^
 At your service\n^
 Admin

set "Server=smtp.domain.com"
set "Port=25"

rem ** Send email test **

echo.
echo Start: Send Email
set Message=Debug test code
c:\APPS\sendemail.exe -f "%FromEmail%" -t "%Recipient%" -cc "%CCRecipient%" -u "%Subject%" -m "%Message%" -v -s "%Server%"

rem ** run bat files and capture error message **

for %%A in (%batFiles%) do (
    call :EMAIL %%A
    if errorlevel 1 exit /b
)
exit /b


:EMAIL
setlocal
echo.

call "%~1"

if errorlevel 1 (
    echo %errorlevel%
    set "exitcode=%errorlevel%"
) else exit /b

rem ** Send email **

if "%~n1" == "FILE1" (
    set "Message=Debug test code %exitcode%"
) else set Message=Execution of '%~1' failed with error message %exitcode%.^
 Examine the logs and fix any issues before next run.\n\nAt your service\nAdmin


echo Start: Send Email
c:\APPS\sendemail.exe -f "%FromEmail%" -t "%Recipient%" -cc "%CCRecipient%" -u "%Subject%" -m "%Message%" -v -s "%Server%"

rem ** force execution to quit if check fails **
if %errorlevel% neq 0 echo Email send error message %errorlevel%.
exit /b

通过优化代码来消除重复等。 它似乎工作得更好。我可能不小心修复了它。

在使用前建议检查echo %errorlevel%中的call set,否则%errorlevel%属于set命令。

新代码均不需要延迟扩展,因此请删除 EnableDelayedExpansion设置。

脚本设置为一个变量,并用作文件集, 在for循环中。

许多set variable=value被双引号以避免 尾随空间问题。那些不是,是多行等 更好。

“发送电子邮件”代码不在标签:EMAIL中,这有助于 合并重复的代码。它会检查名称FILE1是否 是参数,并使用其他电子邮件匹配 您的原始代码。

如果sendemail.exe设置了%errorlevel%,它将结束脚本 设置为非零,稍后在for循环中进行检查。 如果您想退出被调用的子批处理文件, 将最后一行从exit /b更改为exit /b %exitcode%

请注意,exit /b的隐式使用与exit /b %errorlevel%相同。 如果您喜欢以后的版本,请根据自己的喜好更新代码。 如果使用后者,则可能需要延迟变量扩展 在代码块中,即(command & exit /b !errorlevel!)