Bagikan melalui


Running a Scheduled Task after another

Within the Windows Task Scheduler it is possible to fire off processes based on a lot of different triggers, both time based, and windows event based. However it seemed quite hard to fire off one scheduled task after another had completed, despite there being an event log showing the task starting, running and completing:clip_image002[4]

The main reason for running one Scheduled Task after another was due to the change in user running the task, so they could not be chained as the same task.

The following example is much more simplified, but the underlying solution is the same.

I have created a very simple Ping Task which displays a message, and wanted to chain a Pong task to run directly after this has completed. Creating the tasks are quite simple, but now I want to set a trigger on Pong for when the Ping task completes. This proved a little more difficult, though “On Event” appeared to be the right way to go, as the Task Scheduler outputs events at all points in the operation of a Task.

The most interesting one to me was the “Task Completed” event you can see above. Looking at XML view within the details of this event it appeared that I knew all the EventData I needed to know to run the Pong task on:

clip_image004[4]

The trouble was with the Basic On an event trigger, you could only specify the Event ID which is 102 for all Task completed events on all Tasks, and not just my Ping Task:

clip_image006[4]

However it is possible to define a Custom Event, though the standard filter does not allow much control over the selection of the events:

clip_image008[4]

Using this as a starting point, and selecting the most that I could in this dialogue also started to populate the custom XML XPath, which would allow far more control.

clip_image010[4] clip_image012[4]

Now to start writing the XPath and refering to the XML from the TaskCompleted Event:

 <Event xmlns="https://schemas.microsoft.com/win/2004/08/events/event">
    <System>
       <Provider Name="Microsoft-Windows-TaskScheduler" Guid="{DE7B24EA-73C8-4A09-985D-5BDADCFA9017}" />
       <EventID>102</EventID>
       <Version>0</Version>
       <Level>4</Level>
       <Task>102</Task>
       <Opcode>2</Opcode>
       <Keywords>0x8000000000000001</Keywords>
       <TimeCreated SystemTime="2011-10-25T16:20:39.200166100Z" />
       <EventRecordID>109987</EventRecordID>
       <Correlation ActivityID="{13A3621A-839B-4FCD-83F3-B6677F1EC9F2}" />
       <Execution ProcessID="9372" ThreadID="8744" />
       <Channel>Microsoft-Windows-TaskScheduler/Operational</Channel>
    </System>
    <EventData Name="TaskSuccessEvent">
       <Data Name="TaskName">\Ping</Data>
       <Data Name="InstanceId">{13A3621A-839B-4FCD-83F3-B6677F1EC9F2}</Data>
    </EventData>
 </Event>

 

I could use an XPath to get the Data element with TaskName of \Ping:

 <QueryList>
    <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
       <Select Path="Microsoft-Windows-TaskScheduler/Operational">*[EventData
 [@Name='TaskSuccessEvent'][Data[@Name='TaskName']='\Ping']]</Select>
    </Query>
 </QueryList>
  

clip_image014[4]

By adding this trigger, and firing the Ping Event, the Pong Task Fires immediately after the Ping is complete.

Breaking the XPath down further:

clip_image001

It is now a simple case of reusing this XPath replacing the Task Name, \Ping here, with the task to run after.

Comments

  • Anonymous
    January 19, 2012
    Thanks!!! Was struggling on the event data syntax. You have helped me tremendously!!!

  • Anonymous
    April 06, 2012
    Hi Dave, lets say that under the task scheduler library I have a folder named 'XYZ' and I want to start another task ONLY when any of the tasks under this 'XYZ' folder complete. What would the XPath look like?

  • Anonymous
    April 10, 2012
    Hi Chris, Looking at the event details the taskname would be 'XYZ' followed by your event name.  I believe there is a starts-with function within xpath, however I cannot get that to work on my side, the way you could get this working is to use multiple triggers with the xpath [EventData [@Name='TaskSuccessEvent'][Data[@Name='TaskName']='XYZ{your task name here}'] for each events under that folder replacing {your task name here} with each task name in that folder. Hope that helps. Dave

  • Anonymous
    April 10, 2012
    Hi Dave, Thanks for your reply. I was hoping to make a generic filter for any task under the XYZ folder but it looks like thats not possible. Does the Windows Task Scheduler not allow certain functions such as contains, or starts-with?

  • Anonymous
    April 11, 2012
    Found my answer here: msdn.microsoft.com/.../cc231312%28v=prot.10%29.aspx

  • Anonymous
    March 29, 2013
    Thank you for posting this. This was very useful.

  • Anonymous
    May 21, 2013
    Hello, i've another question. Is it possible to start Pong depending on Success of Ping and not before! a specified  time (like ping ends 4 p.m. but Pong shouldn't start before 8 p.m.)? The problem is, that the job has to run every day. Many thanks in advance. Greats Chris

  • Anonymous
    October 30, 2013
    Hi Dave, Thank you.. My task is working by using your tips.

  • Anonymous
    March 06, 2014
    A wonderful post!  I expected I would be searching for hours and having to figure out the XML syntax all on my own.  This will save me sooooo much time in doing essentially what you needed to get done.

  • Anonymous
    July 19, 2014
    Thank you so much for your best clarification now I can mange run task one after the other 10Q again

  • Anonymous
    August 13, 2014
    What if the Task is completed with Exit code other than 0. I want my next task to be started only if the forst one completed with Exit code 0. Thanks.

  • Anonymous
    September 16, 2014
    Hi, thanks for this post, it helped me a lot ! I've gone further by adding the condition "executing a task only if the previous was completed with the exit code 0". In order to do that, the "Action completed" event is better than the "task completed" one. The Event Data element of this "Action completed" event contains one more child element with the name "ResultCode" which is exactly what we are looking for ! So the xPath is : *[EventData[@Name='ActionSuccess'][Data[@Name='TaskName']='Ping'][Data[@Name='ResultCode']='0']] Hope that help some of you Ced

  • Anonymous
    April 15, 2015
    Thanks for your help! I have a question on how you would extend this out in the following scenario.  I have 4 tasks, A, B, C, D. I want to trigger task D based on A, B, and C tasks all succeeding.  What would the XPATH look like in that scenario.

  • Anonymous
    September 06, 2015
    Just wanted to say thanks! =]   It's nigh impossible to find the information in your blog on TechNet, unless someone knew exactly what they were looking for, so thank you :-)

  • Anonymous
    October 23, 2015
    Hi Dave, Is it possible add a date filter to it. Like I would like to know the status of the Task which got completed in the last 7hrs. Then it will trigger the new task ? Francis.

  • Anonymous
    October 29, 2015
    Hello I have 3 tasks, A, B and C. My task C just run when task A and B completed. How I do? It's possible?