Как зафиксировать возвращенный уровень ошибок подпакетного файла и действовать соответствующим образом

Я работаю над пакетным файлом, который вызывает 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 [email protected]
set [email protected]
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, работает нормально.


person mandyallstars    schedule 02.04.2019    source источник
comment
Мне кажется, что ваш c:\APPS\sendemail.exe терпит неудачу и выходит из пакета. Как насчет вставки Echo %errorlevel% & pause в строку: 52. Также я бы подумал о том, чтобы напрямую следовать за call %batchfile1% с условным выполнением || (echo fail...)   -  person    schedule 03.04.2019
comment
Не могли бы вы сократить код до минимально воспроизводимого примера?   -  person aschipfl    schedule 03.04.2019


Ответы (1)


@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 "[email protected]"
set "[email protected]"
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!).

person michael_heath    schedule 03.04.2019