Creating a threaded Windows Service

Posted in: General vb.NET
By dePoPo
Aug 13, 2009 - 11:59:42 AM

Step 1, Creating the project and installation procedures
  • Start Visual Studio, and choose the windows service project type. And empty objects panel appears. Drag any controls you will use onto this panel. Many examples use a timer control, but i choose a different concept for two reasons;

    - Timer controls can be problematic in windows services. The default timer control of a forms application is bugged, and will not - or not always fire. Usage of a system.threading timer is another option that works, but is less intuitive for an example. For more information about using timers in services and the associated problems see:
    BUG: The Elapsed event of the System.Timers.Timer class is not raised in a Windows service

    - You may not want to work with a timed event, and use a continuously running background programm. This example uses such a model. It uses a global variable to indicate wheter the main loop is running, and another one to indicate if a stop request has been received from the service manager. Using these two variables demonstrates how to communicate between the events and the main programm that has been fired off by the service start into a seperate thread.

  • Rightclick the panel, and choose "Add Installer", This will add all the installer objects needed.
    addinstaller_1.jpg



  • On the serviceeprojectinstaller1 object; set the account to Localsystem
    seriviceprocessinstaller.jpg



  • On the serviceinstaller1 object, set the service name and the startup type
    serviceinstaller.jpg



Step 2, Adding the code
  • By double clicking on the service design panel, you will be able to access the actual code for the service.  The complete code is below:

Public Class Service1

    Dim v_shutdownsignal As Boolean = False
    Dim v_mainlooprunning As Boolean = False

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.

        WriteEvent("WinServicedemo v1.0.1 starting", "WinServiceDemo", EventLogEntryType.Information, "WinServiceDemo")

        ' --- Fire the main loop of our programm
        Dim th As New Threading.Thread(AddressOf MainLoop)
        th.IsBackground = True
        th.Start()

    End Sub

    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.


        ' --- Signal the main loop to stop
        v_shutdownsignal = True

        ' --- Wait for the main loop to signal that is has stopped
        While v_mainlooprunning = True

            ' --- Wait for the main loop to die
            System.Threading.Thread.Sleep(10)
            WriteEvent("Waiting for the main loop to stop...", "WinServiceDemo", EventLogEntryType.Information, "WinServiceDemo")

        End While

        ' --- Now the mainloop has shut down cleanly
        WriteEvent("WinServicedemo stopping", "WinServiceDemo", EventLogEntryType.Information, "WinServiceDemo")

    End Sub

    Public Sub MainLoop()

        ' --- This is the main loop of our service

        ' --- Set the global to indicate the stop controller that we are running
        v_mainlooprunning = True

        ' --- Run the main programm until we get a signal that the user stopped the service
        While v_shutdownsignal = False

            WriteEvent("The minute event fired in the main loop", "WinServiceDemo", EventLogEntryType.Information, "WinServiceDemo")
            Dim n_delay As Integer
            While n_delay < 60 And v_shutdownsignal = False  ' wait 60 seconds, OR till a shutdown request
                n_delay = n_delay + 1
                System.Threading.Thread.Sleep(1000)
            End While


        End While

        ' --- Signal that we are done
        v_mainlooprunning = False

    End Sub


    Public Function WriteEvent(ByVal sEntry As String, ByVal sAppName As String, ByVal eEventType As EventLogEntryType, ByVal sLogName As String) As Boolean

        ' --- Write to the eventlog
        '     Source: http://www.dreamincode.net/code/snippet1122.htm
        '     If a non existing logfile is specified, it will be created for us

        Dim oEventLog As New EventLog
        Try
            'Register the Application as an Event Source
            If Not EventLog.SourceExists(sAppName) Then
                EventLog.CreateEventSource(sAppName, sLogName)
            End If

            'log the entry
            oEventLog.Source = sAppName
            oEventLog.WriteEntry(sEntry, eEventType)
            Return True
        Catch Ex As Exception
            Return False
        End Try
    End Function

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)

        ' --- Write an event every tick to the eventlog
        WriteEvent("WinServicedemo timer event", "WinServiceDemo", EventLogEntryType.Information, "WinServiceDemo")

    End Sub
End Class


Step 3 Installing and untinstalling the service
  • BUILD the project. This will result in the binary being present in the project directory.   Move the sercvice executable if you want to another directory where it will be run.

  • Installation of the service ios done with the installutil tool. This tool is directly accessible from a Visual Sutdio command prompt, or from the .NET framework directory in your system directory (eg:)


 Map van C:\windows\Microsoft.NET\Framework\v2.0.50727

27-07-2008  20:03            28.672 InstallUtil.exe
               1 bestand(en)           28.672 bytes

  • run installutil winservicedemo.exe to install the service
    -or-
    run installutil /u winservicedemo.exe to remote the installed service
    seriveceswindow.jpg



  • Finaly, you should be able to see the service in the control panel's service overview, and see the logged events.
    ecentlogdata.jpg



  • Keep in mind that while running and installing your service from the project directory is fine during development, you will need to stop the service to be able to build (the executable will be in use after all)

  • You may want to change the name of the base class of the project (service1 in this example), as that is the name that will be used in the application log by windows to log events about your service.

A zip file containing the source and the binary of this example can be downloaded from the link at the bottom of this article.




Downloads


Visitor Comments