带有任务计划程序 return 代码的嵌套批处理文件

Nested Batch Files with Task Scheduler return codes

我有一些批处理文件 运行 一周中某些天的一些任务,我认为它们工作正常,直到需要这些任务的同事指出我的代码正在发送一封电子邮件说进程失败,但任务计划程序指示任务 运行 正常。然后我们检查了输出,它们似乎是正确的。

基本上我的批处理文件调用另一个批处理文件,那个 运行 是一个可执行文件,有时是一个 python 程序(取决于它是哪个任务)。然后检查该批处理文件的 return 代码并发送相应的电子邮件(我在下面附上了我的这些批处理文件之一的代码)。

我的问题是:如果可执行文件失败,因此内部批处理文件失败并且失败的电子邮件 python 脚本是 运行,那么整个批处理文件 return 是否为 0x00 ?还是 return 内部批处理文件的错误代码 "something" 出错了?

ECHO ON
cd G:\Reports\Batch Files\
G:
call ContactsReview.bat
IF %ERRORLEVEL% NEQ 0 (
    python G:\mtsprograms\python\ContactsFailed.py
)
IF %ERRORLEVEL% EQU 0 (
    python G:\mtsprograms\python\ContactsReviewEmail.py
)

我对这个问题的推理是,如果 ContactsReview.bat 失败并且错误检查 运行 是 ContactsFailed.py 脚本,整个批处理文件是否认为 "Hey, I finished my script, return 0x00"?我写这段代码时假设它会认为 "ContactsReview.bat failed with this error, handle the error, and return errorcode".

您使用if errorlevel 1 if not errorlevel 2 echo exit 1.

您测试 errorlevel 并使用您想要的任何代码退出。见/b参数

想一想 - 您通过 ERRORLEVEL 检测到一个错误,但随后您 运行 另一个命令 (python)。所以现在你的 ERRORLEVEL 报告你的 python 命令的 return 状态,而不是你的 ContactsReview.bat 调用。

如果要保留 ERRORLEVEL,则必须将其保存在变量中,然后可以使用 EXIT /B 使用适当的 return 代码退出主脚本。

需要注意的一件事 - 每次调用 python.exe 等外部命令时,ERRORLEVEL 都会设置为新的 return 代码。但是 cmd.exe 与它处理内部命令的方式不一致。一般情况下,所有内部命令如果发生错误都会设置 ERRORLEVEL(DEL 是一个例外),但一些命令如 ECHO 和 GOTO 不会在成功时清除 ERRORLEVEL,而其他命令如 DIR 和 CD 会在成功时清除 ERRORLEVEL。

无论如何,下面的内容应该可以解决您的问题。

echo on
cd /d G:\Reports\Batch Files\
call ContactsReview.bat
set "err=%errorlevel%"
if %err% neq 0 (
    python G:\mtsprograms\python\ContactsFailed.py
) else (
    python G:\mtsprograms\python\ContactsReviewEmail.py
)
exit /b %err%

阅读%errorlevel%

Almost all applications and utilities will set an exit code when they complete/terminate.

  • 注意almost all并不代表all;相反,很多命令保持 %errorlevel% 不变。
  • 但是,CLI 和批处理脚本中的非零错误级别总是(至少)由语法错误引发。

所以你的 ContactsReview.bat 可以如下所示 (note exit /B %AppErrorlevel%); :

:: some stuff
:: clear errorlevel before calling your app:
(call ) 
:: execute your app (executable) here
:: remember errorlevel raised by your app:
set /A "AppErrorlevel=errorlevel"
:: other stuff which could raise non-zero error level although your app succeeds
:: force your batch to return right errorlevel code: 
exit /B %AppErrorlevel%

了解更多如何通过 (call ) 命令强制 %errorlevel%0 在 dbenham 对 SuperUser 另一个问题的回答:setting ERRORLEVEL to 0:

If you want to force the errorlevel to 0, then you can use this totally non-intuitive, but very effective syntax: (call ). The space after call is critical. If you want to set the errorlevel to 1, you can use (call). It is critical that there not be any space after call.

(call)
echo %errorlevel%
(call )
echo %errorlevel%