ARTICLE

Application Scheduler Service Using VB.Net And XML

Posted by Ajith Kumar Radhakrishnan Articles | Visual Basic 2010 December 07, 2006
This is an application scheduler that is implemented as a Windows Service, similar to the Windows Task Scheduler - but simple, as it has fewer configuration options and it uses XML to store and retrieve data.
Reader Level:

This is an application scheduler that is implemented as a Windows Service, similar to the Windows Task Scheduler - but simple, as it has fewer configuration options and it uses XML to store and retrieve data.

 

The program uses System.Timers, System.Threading and System.Diagnostics to repeatedly loop through the XML data to see whether an application is scheduled to run at the present time or not, and if yes, to launch it as a new process in a new thread.

 

The source

 

Imports System

Imports System.Collections

Imports System.ComponentModel

Imports System.Data

Imports System.Diagnostics

Imports System.ServiceProcess

Imports System.Xml

Imports System.Timers

Imports System.Threading

Imports System.Configuration

Imports System.IO

 

Namespace AppScheduler

  

   Public Class AppScheduler

      Inherits System.ServiceProcess.ServiceBase

      Private configPath As String

      Private _timer As New System.Timers.Timer()

      Private dsTasks As New DataSet()

      Private formatString As String = "MM/dd/yyyy HH:mm:ss"

      '/ <summary>

      '/ Required designer variable.

      '/ </summary>

      Private components As System.ComponentModel.Container = Nothing

     

      '/ <summary>

      '/ Class that launches applications on demand.

      '/ </summary>      

      Class AppLauncher

         Private app2Launch As String

        

         Public Sub New(path As String)

            app2Launch = path

         End Sub 'New

        

         Public Sub runApp()

            Dim pInfo As New ProcessStartInfo(app2Launch)

            pInfo.WindowStyle = ProcessWindowStyle.Normal

            Dim p As Process = Process.Start(pInfo)

         End Sub 'runApp

      End Class 'AppLauncher

     

      Sub timeElapsed(sender As Object, args As ElapsedEventArgs)

         Dim currTime As DateTime = DateTime.Now

         Dim dRow As DataRow

         For Each dRow In  dsTasks.Tables("task").Rows

            Dim runTime As DateTime = Convert.ToDateTime(dRow("time"))

            If currTime >= runTime Then

               Dim exePath As String = dRow("exePath").ToString()

               Dim launcher As New AppLauncher(exePath)

               New Thread(New ThreadStart(AddressOf launcher.runApp)).Start()

               ' Update the next run time

               Dim strInterval As String = dRow("repeat").ToString().ToUpper()

               Select Case strInterval

                  Case "D"

                     runTime = runTime.AddDays(1)

                  Case "W"

                     runTime = runTime.AddDays(7)

                  Case "M"

                     runTime = runTime.AddMonths(1)

               End Select

               dRow("time") = runTime.ToString(formatString)

               dsTasks.AcceptChanges()

               Dim sWrite As New StreamWriter(configPath)

               Dim xWrite As New XmlTextWriter(sWrite)

               dsTasks.WriteXml(xWrite, XmlWriteMode.WriteSchema)

               xWrite.Close()

            End If

         Next dRow

      End Sub 'timeElapsed

       

      Public Sub New()

         ' This call is required by the Windows.Forms Component Designer.

         InitializeComponent()

      End Sub 'New

      

      ' TODO: Add any initialization after the InitComponent call

      ' The main entry point for the process

      Shared Sub Main()

         Dim ServicesToRun() As System.ServiceProcess.ServiceBase

        

         ' More than one user Service may run within the same process. To add

         ' another service to this process, change the following line to

         ' create a second service object. For example,

         '

         '   ServicesToRun = new System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};

         '

         ServicesToRun = New System.ServiceProcess.ServiceBase() {New AppScheduler()}

         System.ServiceProcess.ServiceBase.Run(ServicesToRun)

      End Sub 'Main

      

      '/ <summary>

      '/ Required method for Designer support - do not modify

      '/ the contents of this method with the code editor.

      '/ </summary>

      Private Sub InitializeComponent()

         '

         ' AppScheduler

         '

         Me.CanPauseAndContinue = True

         Me.ServiceName = "Application Scheduler"

      End Sub 'InitializeComponent

         

      '/ <summary>

      '/ Clean up any resources being used.

      '/ </summary>

      Protected Overrides Sub Dispose(disposing As Boolean)

         If disposing Then

            If Not (components Is Nothing) Then

               components.Dispose()

            End If

         End If

         MyBase.Dispose(disposing)

      End Sub 'Dispose     

     

      '/ <summary>

      '/ Set things in motion so your service can do its work.

      '/ </summary>

      Protected Overrides Sub OnStart(args() As String)

         ' TODO: Add code here to start your service.

         configPath = ConfigurationSettings.AppSettings("configpath")

         Try

            Dim xRead As New XmlTextReader(configPath)

            Dim xvRead As New XmlValidatingReader(xRead)

            xvRead.ValidationType = ValidationType.DTD

            dsTasks.ReadXml(xvRead)

            xvRead.Close()

            xRead.Close()

         Catch Else

            Dim srvcController As New ServiceController(ServiceName)

            srvcController.Stop()

         End Try

         _timer.Interval = 30000

         AddHandler _timer.Elapsed, AddressOf timeElapsed

         _timer.Start()

      End Sub 'OnStart     

     

      '/ <summary>

      '/ Stop this service.

      '/ </summary>

      Protected Overrides Sub OnStop()

      End Sub 'OnStop

   End Class 'AppScheduler ' TODO: Add code here to perform any tear-down necessary to stop your service.

End Namespace 'AppScheduler

       

I have created a class named AppLauncher that accepts the executable name of a program as its constructor parameter. There is a method RunApp() in the class that creates a new ProcessInfo object with the specified path and calls Process.Start(ProcessInfo) with the ProcessInfo object as its parameter.

 

Class that launches applications on demand

 

Class AppLauncher

    Private app2Launch As String

    Public Sub New(ByVal path As String)

        app2Launch = path

    End Sub 'New

    Public Sub runApp()

        Dim pInfo As New ProcessStartInfo(app2Launch)

        pInfo.WindowStyle = ProcessWindowStyle.Normal

        Dim p As Process = Process.Start(pInfo)

    End Sub 'runApp

End Class 'AppLauncher

 

I had to create a separate class to launch an application in a new thread, because the Thread class in .Net 2003 does not allow you to pass parameters to a thread delegate (whereas you can do so in .Net 2005). The ProcessStartInfo class can be used to create a new process. The static method Start (ProcessInfo) of the Process class returns a Process object that represents the process started.

 

There is a Timer variable used in the program, named _timer. The event handler for the timer's tick event is given below:

 

Event handler for the timer's tick event

 

Sub timeElapsed(sender As Object, args As ElapsedEventArgs)

      Dim currTime As DateTime = DateTime.Now

      Dim dRow As DataRow

      For Each dRow In  dsTasks.Tables("task").Rows

        Dim runTime As DateTime = Convert.ToDateTime(dRow("time"))

     Dim formatString As String = "MM/dd/yyyy HH:mm"

     If(runTime.ToString(formatString)==currTime.ToString(formatString))Then

       Dim exePath As String = dRow("exePath").ToString()

           Dim launcher As New AppLauncher(exePath)

           New Thread(New ThreadStart(AddressOf launcher.runApp)).Start()

           ' Update the next run time

           Dim strInterval As String = dRow("repeat").ToString().ToUpper()

           Select Case strInterval

              Case "D"

                runTime = runTime.AddDays(1)

              Case "W"

                runTime = runTime.AddDays(7)

              Case "M"

                runTime = runTime.AddMonths(1)

              End Select

              dRow("time") = runTime.ToString(formatString)

              dsTasks.AcceptChanges()

              Dim sWrite As New StreamWriter(configPath)

              Dim xWrite As New XmlTextWriter(sWrite)

              dsTasks.WriteXml(xWrite, XmlWriteMode.WriteSchema)

              xWrite.Close()

       End If

    Next dRow

End Sub 'timeElapsed            

 

An easy way to compare date and time disregarding some particular values such as hour of the day or minute or second: convert them to the appropriate string format first, and check whether the two strings are equal. Otherwise, you have to individually check each item you want to compare, like If(currTime.Day==runtime.Day && currTime.Month==runtime.Month && ...). The interval values are : "D" (for daily schedule), "W" (for weekly schedule), and "M" (for monthly schedule). The values are read from an XML file named AppScheduler.xml. The file format is given below:

 

The XML file containing list of applications to launch

 

<?xml version="1.0" encoding="utf-8" ?>

<!DOCTYPE appSchedule[

<!ELEMENT appSchedule (task*)>

<!ELEMENT task EMPTY>

<!ATTLIST task name CDATA #REQUIRED>

<!ATTLIST task exePath CDATA #REQUIRED>

<!ATTLIST task time CDATA #REQUIRED>

<!ATTLIST task repeat (D|W|M) #REQUIRED>

<appSchedule>

          <task name="Notepad" exePath="%SystemRoot%\system32\notepad.exe" time="05/05/2006 10:45" repeat="D"/>

          <task name="Wordpad" exePath="C:\Program Files\Outlook Express\msimn.exe" time="05/05/2006 10:46" repeat="W"/>

          <task name="Calculator" exePath="%SystemRoot%\System32\calc.exe" time="05/05/2006 10:47" repeat="M"/>

</appSchedule>

 

Starting the service

 

Protected Overrides Sub OnStart(args() As String)

   ' TODO: Add code here to start your service.

    configPath = ConfigurationSettings.AppSettings("configpath")

    Try

        Dim xRead As New XmlTextReader(configPath)

        Dim xvRead As New XmlValidatingReader(xRead)

        xvRead.ValidationType = ValidationType.DTD

        dsTasks.ReadXml(xvRead)

        xvRead.Close()

        xRead.Close()

     Catch Else

         Dim srvcController As New ServiceController(ServiceName)

         srvcController.Stop()

      End Try

      _timer.Interval = 30000

      AddHandler _timer.Elapsed, AddressOf timeElapsed

      _timer.Start()

End Sub 'OnStart

 

The path of the XML file is set in the App.config file (the IDE will not create this file automatically, so you will have to manually add one into your project) in the following way:

 

App.config

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

          <appSettings>

                   <add key="configpath" value="C:\AppScheduler.xml"/>

          </appSettings>

</configuration>

 

An XmlValidatingReader is used to ensure that the data strictly confirms to the DTD. The catch block stops the service, if some error occurs while trying to load data from the XML file. The timer interval is set to 30 seconds on starting the service.

 

To install/unistall the service

 

Build the application. Copy the AppScheduler.xml file to your C:\. Select Start > Programs > Microsoft Visual Studio .NET 2003 > Visual Studio .NET Tools > Visual Studio .NET 2003 Command Prompt. Go to the \bin\release folder in the project directory. Type the following command:

 

installutil AppScheduler.exe

 

Now, go to control panel. Select Performance and Maintenance > Administrative Tools and select Services. Doble-click on the AppScheduler service. Select the Log on tab. Check the Allow this service to interact with desktop checkbox. Click OK. Then click on the Start Service(}) button in the toolbar.

 

To uninstall the service, in the Visual Studio .NET command prompt, go to the \bin\release folder in the project directory and enter:

 

installutil /u AppScheduler.exe

 

Summary

 

Creating Windows services is fun, once you learn the basic things to do. XML is really a great tool that makes

lot simple to define data and behavior using plain text files.

NOTE: THIS ARTICLE IS CONVERTED FROM C# TO VB.NET USING A CONVERSION TOOL. ORIGINAL ARTICLE CAN BE FOUND ON C# CORNER (http://www.c-sharpcorner.com/).

share this article :
post comment
 

Hi -- I'm a newbie to this website so still learning to navigate. I submitted the below asking for help. Didn't know where it went. Sorry if it's a duplication. Although few years back on this topic but it becomes a need for me. Compiled your program successfully. Followed your instruction. All went good up to where started the service. The problem is: "Could not start the AppScheduler service on Local Computer. Error 1053: The service did not respond to the start or control request in a timely fashion". I'm a beginner. Have not had the personal experience to code using either thread or service. Only I read the white paper and tried some code snippets. Please help. I'm using VB.Net of VS Studio 2008 .Net Framework 3.5 SP1. Thanks!!!

Posted by baonet Feb 17, 2011

Hi Friend, Thanks for such helpful and nice artical. Acc.to this artical.I have created one sample window service which will automatically start the exe (e.g notepad.exe). but my problem is that exe (e.g notpad.exe) is starts but no application is launches.even i can see the running exe in task manager. how to slove this problem?. waiting for reply, thanks in advanced.

Posted by Lalit Patil May 17, 2007

Hi Friend, Thanks for such helpful and nice artical. Acc.to this artical.I have created one sample window service which will automatically start the exe (e.g notepad.exe). but my problem is that exe (e.g notpad.exe) is starts but no application is launches.even i can see the running exe in task manager. how to slove this problem?. waiting for reply, thanks in advanced. Regards, Lalit Vasant Patil. Software Engineer (Nashik-Maharashtra)

Posted by Lalit Patil May 17, 2007

On executing the same, i got the below error log; No public installers with the RunInstallerAttribute.Yes attribute could be found in the \appscheduler\bin\appscheduler.exe assembly. Committing assembly '\appscheduler\bin\appscheduler.exe'. Affected parameters are: assemblypath = \appscheduler\bin\appscheduler.exe logfile = \appscheduler\bin\appscheduler.InstallLog No public installers with the RunInstallerAttribute.Yes attribute could be found in the \appscheduler\bin\appscheduler.exe assembly. Remove InstallState file because there are no installers. Thanks in Advance, Chandru

Posted by Chandru Elango Mar 01, 2007

Hi i'm trying this example butte i always get errors after open vb.net file, cold you pls tell me how do build this project, I’m very interesting on this. Butte if this works like you say i have to make some changes on the code to do what i need. I only develop in vb not in C# if you cold help i appreciate. Tks Mpires

Posted by Miguel Feb 15, 2007
6 Months Free & No Setup Fees ASP.NET Hosting!
Become a Sponsor
PREMIUM SPONSORS
  • ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications. Visit DynamicPDF here
    Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Team Foundation Server Hosting
Become a Sponsor