Search code examples
windowsbatch-filecmderrorlevel

How do I get code 202 from a cmd file launched by Task Scheduler?


Environment: Windows Server 2008 R2

Microsoft Windows Task Scheduler executes a DoThis.cmd file which always returns the ERRORLEVEL in an Event 201 (Success), even though it failed:

Task Scheduler successfully completed task "\Why Cant This Task Fail" , instance "{c8655567-5f1c-4eb2-a2e1-91d2cd0405be}" , action "C:\Windows\SYSTEM32\cmd.exe" with return code 399.

I wish to have it return an Event 202 (Failure) if there is a non-zero ERRORLEVEL, and an Event 201 (Success) if a zero is returned.

My Batch file DoThis.cmd contains

RETURN 399

Thank you, ~ Shaun


Solution

  • I don't believe this is possible by default. The task itself completed successfully, in the sense that it ran at the scheduled time and launched whatever application(s) you wanted it to. The fact that one of the applications raised an error is none of the Task Scheduler's concern.

    However, I was able to achieve almost what you want: you can raise error 203 on one of the actions (not on the task itself) by making sure that the task cannot find the program it is supposed to run as part of the task.

    So I created a Task that runs 3 actions:

    1. MyActualBatch.cmd
    2. MyExe.exe
    3. MyResult.cmd

    The MyBatch.cmd file contains the following code:

    @echo off
    if exist MyExe.exe  del MyExe.exe
    if exist result.cmd del result.cmd
    set myError=0
    :: *********** Do all your processing here **********
    ::    .....
    ::    Store your specific error code in %myError%, or to 0 to indicate success e.g.:
          set myError=399
    ::    .....
    :: *********** End batch file with following lines **********
    if /I %myError% EQU 0 (
       :: No error, so let's copy some small executable that the task can actually run
       :: without impacting the results of the task
       copy /y C:\Windows\System32\ipconfig.exe MyExe.exe > nul
    )
    :: Create a batch file that will instantly exit using the original error code
    :: created in this one
    echo exit /b %myError% > result.cmd
    exit /b %myError%
    

    (or, without the comments that clutter the display):

    @echo off
    if exist MyExe.exe  del MyExe.exe
    if exist result.cmd del result.cmd
    set myError=399
    if /I %myError% EQU 0 (
       copy /y C:\Windows\System32\ipconfig.exe MyExe.exe > nul
    )
    echo exit /b %myError% > result.cmd
    exit /b %myError%
    

    Whenever your batch file needs to raise an error, you set the myError variable to the value you want to return (I prefer using my own variable rather than relying on the ERRORLEVEL system var, which can be reset by just about any action).

    At the end of the script, some code checks if the myError var contains 0 (which means no error occurred). If it does, then the batch creates an executable file named MyExe.exe that the task will be able to run immediately after this batch file ends. But if myError contains a different error value, then the MyExe file will not be created, which will trigger a 203 error in the task when it attempts to run it next.

    Finally, a Result.cmd file is also created so it can be run as the last action by the task, bubbling up the error code you had created in the first task.

    Note: the MyExe file is just a copy of IpConfig.exe. I picked that executable simply because AFAIK it's available on all Windows versions, it's small, and it just lists information so it can't break anything by running as part of the task.