4

I have the following .bat script:

set /a num=%random% %%2
exit /b %num%

I would like to execute that batch script in Windows Task Scheduler in such a way that when the exit code is 1 Task Scheduler sends an email that the script failed.

I can create a different task that monitors the events, but I cannot see any difference in events based on the exit code of the bat script.

This is what the History looks like for both exit code = 0 and = 1.

enter image description here

The difference between exit 0 and exit 1 is that the eventId = 201 has a note in it saying what the exit code was.

2 Answers2

3

The trouble with Task Scheduler is no matter what exit code is returned, the task always logs an Event ID 201 - Action Completed... which is correct... no matter what, the task completed even if the job that was run failed internally.

Looking further, clicking on the Details tab when viewing the logged Event, we can see the ResultCode in the EventData does get set correctly. So it's a simple job to filter that through the GUI right?.... well no... There is no filter beyond EventID. Now we have to write a custom Event filter to trigger on based on the ResultCode. The XML XPath query that we need is this:

<QueryList>
  <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
    <Select Path="Microsoft-Windows-TaskScheduler/Operational">
      *[System[(Level=4 or Level=0) and (EventID=201)]]
        and
      *[EventData[Data[@Name='ResultCode'] and (Data='2147942401')]]</Select>
  </Query>
</QueryList>

So to break it down, we want:

Event log: Microsoft-Windows-TaskScheduler/Operational
Event Level: 4 or 0 = Information
Event ID: 201
And
Event Data: ResultCode = 2147942401

If we set the bad exit code to 1, why is ResultCode = 2147942401? because it actually returns 0x1 which is hexadecimal 0x80070001 which equals decimal 2147942401. So, to get the "Correct" Result code, you will have to find your event, and click on the Details tab, then you can find the "Correct" ResultCode to filter on.

HAL9256
  • 261
  • I am voting this answer up because it is very detailed, but it does not tell me how to look at the "Details of the Event" programmatically such that I could systematically act on the failed script. BTW: I have recently switched to VisualCron to have more flexibility so this question is not of interest to me anymore. – Be Kind To New Users Dec 22 '18 at 04:44
  • You're right, I edited the post to clarify that you have to look at the "Details" tab to get the additional information needed. – HAL9256 Dec 24 '18 at 18:26
  • Sorry, my comment was not clear. The important part of my objection to marking this good answer as the correct answer was that I want to do this programmatically. That is: run a script based on that exit code; not just look at it with my eyeballs. – Be Kind To New Users Dec 24 '18 at 23:30
  • It seems pretty weird that Task Scheduler would equate a returned exit code ox1 as 0x80070001. I was thinking that, maybe the 0x8007 in the high word was the event ID; but 201, in hex is 0xC9. It's like it's pulling a number out of its butt and sticking it in the high word of the result code when the exit code isn't 0. – RobH Feb 14 '24 at 17:25
2

My answer is based on the answer by HAL9256, thank you very much for pointing me the right way.

It turns out that the same exact XML query that works to view events (such as in Event Viewer in a custom view - very handy for debugging the query) also works to trigger a task in a Custom event filter.

  1. Start by adding a new trigger for your task that you want to happen when another task fails (May be the same task for automatic retries!)
  2. At the top of the New Trigger (or Edit Trigger) dialog, for Begin the task: choose On an event
  3. For the Settings choose Custom, then click the New Event Filter button. (It will be Edit Event Filter if returning to edit later)
  4. A new dialog box will open, click the XML tab at the top of it
  5. Check the Edit query manually option and acknowledge the warning.
  6. Enter the XML to use. Here's what I ended up with:

<QueryList>
  <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
    <Select Path="Microsoft-Windows-TaskScheduler/Operational">
      *[System[(EventID=201)]]
        and
      *[EventData
          [Data[@Name='ResultCode']!=0]
          [Data[@Name='TaskName']='\PATH-TO-TASK-BEING-WATCHED']
       ]
    </Select>
  </Query>
</QueryList>

For the asker's question specifically, change the !=0 (triggered by any non-zero exit code) to =2147942401 (exit code 1) And of course change the all-caps path to the path inside of Task Scheduler for the task you want monitor (can be the same one this trigger is on.)

Then click all the OK buttons, changing any other options you want along the way.

davidgro
  • 121