Windows 7 Task Scheduler:How to send email alerts from failed task executions


I try to automate as much as I can with Windows 7 Task Scheduler but I found out Task Scheduler does not check at all the return code of the completed program. It always shows tasks status as "Action completed" no matter what errors happened during the execution. Because it always shows as completed, it's not possible to automatically send an email if task fails. Because it never fails.

There was not any decent answer even in Microsoft's Technet. So I had to dig into XPath event filters to get it working.

Creating the XPath filter

First we create the appropriate XPath filter. We can test the filter in Event viewer. Open Event viewer and open context menu for "Custom Views". Select "Create custom view". A window opens and select it's tab "XML". Check "Edit query manually", pass the warning  and copy-paste this filter there:

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


Press "Ok" and "Save filter to Custom View" windows opens. Give the custom view a name and press "Ok". Now you have a view that should show all tasks that reported completed but actually have return code other than 0.

XPath syntax seems to be simple so you can try other search conditions also. You may have to blacklist or whitelist what programs you want alerts from. There are tasks that will return codes other than 0 even when the execution was ok. For instance task action "Display a Message" returns 1 as a result code so if you create a task that triggers on failed executions and as an action shows a message, you will end up with infinite loop...

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

            ( Data[@Name="TaskName"]!="\DONT_SHOW_THIS_TASK" and
            Data[@Name="TaskName"]!="\DONT_SHOW_THIS_TASK_TOO")
         ]]
    </Select>
  </Query>
</QueryList>


Using XPath filter as an event trigger

When you have a working filter we can create scheduled task for it. Create a new task and select "On an event" as a trigger. Select "Custom" instead of "Basic" and press "Edit Event filter". Select tab "XML" and copy-paste your filter there.

Sending mail as an event action

I don't have any easy answers for you about setting the mail. The "Send an e-mail" action in Task Scheduler does not work with mail systems that require authentication.
I have Cygwin environment and configured SSMTP for these type of mails so I simply created a batch file to call SSMTP to send me an email.
One problem is you don't get any information in mail about what actually went wrong. You can only trigger static emails "Something is wrong". With cron it's easier because it sends you stderr as message body.

Using Powershell scripts as Tasks

One thing to remind you is if you are using Powershell scripts, you should always use -command instead of -file.
If you have task:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -nologo -file BadJob.ps1
It does not return Result code! This is an obvious bug in Powershell.

You have to use: 
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noninteractive -nologo -command .\BadJob.ps1


Conclusion

Creating email alerts is a lot harder than it should be. XPath syntax is not for average users and without it there's no way to check for task failures. I already installed Cygwin's cron to bypass Windows Task Scheduler but then decided to check this XPath feature. Cron does not have fancy GUI but getting it to send mails with enough information about the failure is easier in the end if you already have a working Cygwin environment and know how to use unix.

Comments

  1. The XPath filter is brilliant and exactly what I was looking for.

    I use PowerShell to send the email alerts. Just have the action call PowerShell and pass -command EmailAlert.ps1 -TaskID 101. Or whatever task ID the alert is for. This will grab that last task ID that matches and include in the email.

    # Parameters are variables too
    param ([parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][int[]]$taskid)

    # Computer specific variables
    $computer = (Get-Childitem env:computername).Value
    $logname = "Microsoft-Windows-TaskScheduler/Operational"
    $event = get-winevent -FilterHashtable @{Logname=$logname;ID=$taskid} -MaxEvents 1

    # Email specific variables
    $from = "$computer<$computer@fictional.com>"
    $to = "thing1@fictional.com, thing2@fictional.com"
    $subject = $event.TaskDisplayName + " - " + $computer
    $body = $event.Message
    $smtpserver = "smtp.fictional.com"

    # Send email
    Send-MailMessage -From $from -To $to -Subject $subject -Body $body -SmtpServer $smtpserver

    ReplyDelete

Post a Comment