Creating a Task Scheduler App with Visual Basic

There are times that an app needs to perform a function at a specific time and date: once a week, once a month, every day, twice a month, and so on. There are apps specifically designed for this purpose. The app gets set up through the Windows Task Scheduler and executes on the set time(s) and date(s). Today, we will create an app that can set up task schedules automatically as well as investigate the current schedules of apps.

Windows Task Scheduler

According to MSDN, The Task Scheduler enables you to automatically perform routine tasks on a chosen computer. The Task Scheduler does this by monitoring whatever criteria you choose to initiate the tasks and then executing the tasks when the criteria is met.

The following tasks can be scheduled to execute:

  • When a specific system event occurs
  • At a specific time
  • At a specific time on a daily schedule
  • At a specific time on a weekly schedule
  • At a specific time on a monthly schedule
  • At a specific time on a monthly day-of-week schedule
  • When the computer enters an idle state
  • When the task is registered
  • When the system is booted
  • When a user logs on

Task Scheduler Wrapper

There exists a wrapper for the Windows Task Scheduler. This wrapper can be found on CodePlex. CodePlex is Microsoft’s free open source project hosting site. Here, you can create projects to share with others, collaborate with others on their projects, and even download open source software.

The Task Scheduler Managed Wrapper provides a wrapper for the Windows Task Scheduler. A wrapper “wraps” or “encapsulates” the functionality of another class or component. Wrappers provide a level of abstraction from the implementation of the underlying class or component.

We will make use of this wrapper in our project. You can download it directly from CodePlex. You also can read up on its documentation here.

Our Project

Start Visual Studio and create a new Windows Forms Project. Once the form is displayed, design your form to resemble Figure 1.

Our Design
Figure 1: Our Design

After you have downloaded the Wrapper (in the link given earlier), you need to set a reference to it in your program. You do this by selecting Project, Add Reference. Select the Browse tab and browse to the DLL file’s location, as shown in Figure 2.

Reference
Figure 2: Reference

The Reference to the Task Scheduler Wrapper has now been added to your app. You can make use of its full power.

Code

Import the library that you have referenced earlier:

Imports Microsoft.Win32.TaskScheduler

Add the next code behind the button labeled ‘Create A Task’:

      Using tService As New TaskService()

         Dim tDefinition As TaskDefinition = tService.NewTask
         tDefinition.RegistrationInfo.Description = _
            "Example Task"

         Dim tTrigger As New WeeklyTrigger()

         tTrigger.StartBoundary = DateTime.Today.AddDays(2)
         tTrigger.DaysOfWeek = DaysOfTheWeek.Saturday Or _
            DaysOfTheWeek.Sunday
         tTrigger.WeeksInterval = 5
         tTrigger.Repetition.Duration = TimeSpan.FromHours(4)
         tTrigger.Repetition.Interval = TimeSpan.FromMinutes(10)
         tDefinition.Triggers.Add(tTrigger)

         tDefinition.Actions.Add(New ExecAction("notepad.exe", _
            "c:\Example Task.log"))

         tService.RootFolder.RegisterTaskDefinition("Example Task", _
            tDefinition)

      End Using

A TaskDefinition object gets created; it contains the Task’s information, such as its name. A Trigger is set up. I will speak about Triggers a bit later. After the WeeklyTrigger object has been set up, an ExecAction gets added to the TaskDefinition object. ExecAction is responsible for executing an application, such as Notepad in the preceding example. The last task is to register the Task inside Windows via the help of the TaskService’s RegisterTaskDefiition method.

Creating Different Triggers

You can create the various types of Triggers with code similar to the following:

      'Boot Trigger'
      Dim tBoot As New BootTrigger()
      tBoot.Delay = TimeSpan.FromMinutes(3)

      'DailyTrigger'
      Dim tDaily As New DailyTrigger()
      tDaily.StartBoundary = DateTime.Today _
         + TimeSpan.FromHours(10)
      tDaily.DaysInterval = 4
      tDaily.RandomDelay = TimeSpan.FromHours(2)

      'IdleTrigger'
      Dim tIdle As New IdleTrigger()
      tIdle.ExecutionTimeLimit = TimeSpan.FromMinutes(30)

      'LogonTrigger'
      Dim tLogon As New LogonTrigger()
      tLogon.Delay = TimeSpan.FromMinutes(15)
      tLogon.UserId = "HTG"

      'MonthlyTrigger'
      Dim tMonthly As New MonthlyTrigger()
      tMonthly.StartBoundary = DateTime.Today.AddDays(1)
      tMonthly.DaysOfMonth = New Integer() {27, 24}
      tMonthly.MonthsOfYear = MonthsOfTheYear.July Or _
            MonthsOfTheYear.August
      tMonthly.RunOnLastDayOfMonth = False

      'MonthlyDOWTrigger'
      Dim tMonthlyDOW As New MonthlyDOWTrigger()
      tMonthlyDOW.StartBoundary = DateTime.Today _
         + TimeSpan.FromHours(1)
      tMonthlyDOW.DaysOfWeek = DaysOfTheWeek.Saturday
      tMonthlyDOW.MonthsOfYear = MonthsOfTheYear.January Or _
         MonthsOfTheYear.December
      tMonthlyDOW.WeeksOfMonth = WhichWeek.FirstWeek Or _
         WhichWeek.LastWeek

      'TimeTrigger'
      Dim tTime As New TimeTrigger()
      tTime.StartBoundary = New DateTime(DateTime.Today.Year, _
         12, 31, 23, 59, 0)

      'EventTrigger'
      Dim eTrigger As New EventTrigger()
      eTrigger.Subscription = "<QueryList><Query Id='1'> _
        <Select Path='System'> *[System/Level=2]</Select></Query> _
         </QueryList>"
      eTrigger.ValueQueries.Add("Name", "Value")

      'RegistrationTrigger'
      Dim rTrigger As New RegistrationTrigger()
      rTrigger.Delay = TimeSpan.FromMinutes(5)

      'SessionStateChangeTrigger'
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.ConsoleConnect, _
         Key .UserId = "joe" _
      }
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.ConsoleDisconnect _
      }
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.RemoteConnect _
      }
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.RemoteDisconnect _
      }
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.SessionLock, _
       Key .UserId = "joe" _
      }
      New SessionStateChangeTrigger() With { _
         Key .StateChange = TaskSessionStateChangeType.SessionUnlock _
      }

More information about Triggers can be found here.

Add the following code to identify a Task and then do something productive with it. For example, you can Delete it:

Private Sub GetAndDeleteTask(strTaskName As String)

   Using tService As New TaskService()

      Dim tTask As Task = tService.GetTask(strTaskName)

      If tTask Is Nothing Then

         Return

      End If

      tTask.Definition.Triggers(0).StartBoundary = _
         DateTime.Today + TimeSpan.FromDays(2)
      tTask.RegisterChanges()

      tService.RootFolder.DeleteTask(strTaskName)

   End Using

End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) _
   Handles Button3.Click

   GetAndDeleteTask("NameOfTask")

End Sub

Add the following code to display a list of all tasks that are scheduled to run with the Windows Task Scheduler:

   Private Sub ShowAllTasks()

      Using tService As New TaskService()

         ShowFolderTasks(tService.RootFolder)

      End Using

   End Sub

   Private Sub ShowFolderTasks(tFolder As TaskFolder)

      For Each tTask As Task In tFolder.Tasks

         DisplayDetails(tTask)

      Next

      For Each tSubFolder As TaskFolder In tFolder.SubFolders

         ShowFolderTasks(tSubFolder)

      Next

   End Sub

   Private Sub DisplayDetails(tTask As Task)

      ListBox1.Items.Add(tTask.Name + "" + tTask.Path + "" _
         + tTask.LastRunTime)

   End Sub

   Private Sub Button4_Click(sender As Object, e As EventArgs) _
      Handles Button4.Click

      ShowAllTasks()

   End Sub

This loops through all the Root tasks and their respective SubRoot Tasks and displays the particular tasks’ details.

All Tasks
Figure 3: All Tasks

Conclusion

Having the ability to manipulate the Windows Task Scheduler from a separate program is quite awesome. It comes in very handy, especially when the task you need to schedule is on a separate server.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read