Click here to Skip to main content
11,706,007 members (58,960 online)
Click here to Skip to main content

XwServiceBase - A Windows Service Template

, 21 Nov 2010 CPOL 11.7K 206 32
Rate this:
Please Sign up or sign in to vote.
A template to use as a "starter kit" for new Windows services

Introduction

As we all know, sometimes we have the necessity of running tasks at predefined times. Windows has "Schedule tasks", and they are very useful and reliable. However, I always find myself grinding my teeth when using them because I don't want to make a script or command line for every little thing. And that is where the Windows services get into action...

However, I don't like depending on "installutil.exe" to install and uninstall services. I would rather have it standalone. So I got my requirements together and set to work on a code base that I could use as a Windows service.

This code is that code base I use every time I need a new service. I just copy the solution, and change its name. Instant service!

What This Gives Me?

  • Multiple threads configured on the app.config
  • Individual log files for each thread (errors and messages)
  • Possibility of sending errors by mail
  • In debug (under Visual Studio or not), runs as console application
  • In Release, runs as Service
  • It can run as Console Application in release mode when started with "-c" switch
  • Self Install and uninstall, avoiding external tools

Examples

Here's an example of the output:

*******************************************************************************
XWega Service Base                                           V:1.0.0.1
===============================================================================
WARNING: this is a debug version
===============================================================================
-------------------------------------------------------------------------------
29-08-2010 20:30:51.2964 => SVR : Service Started (Debug)
29-08-2010 20:30:51.3214 => Thread1          : STARTING...
29-08-2010 20:30:51.3214 => Thread1          : do your stuff
29-08-2010 20:30:51.3264 => Thread1          : ...DONE!

The possible command switch (shown by "-h"):

*******************************************************************************
XWega Service Base                                           V:1.0.0.1
===============================================================================
HELP:
-c : Run as console application
-i : Install service
-u : Uninstall service

Example of the app.config

<appThreads enabled="true" abortTimeout="00:10:00">
	<thread enabled="true" runOnStart="true" recurse="true"  time="00:00:10"
		name="ThreadThatDoSomething" method="Thread1.GO" workingFolder="" />
	<thread enabled="true" runOnStart="true" recurse="true"  time="00:01:00"
		name="ThreadThatTrys" method="Thread2.GO" workingFolder="" />
	<thread enabled="true" runOnStart="true" recurse="false" time="01:00:00"
		name="ThreadThatBeleive" method="Thread3.GO" workingFolder="" />
</appThreads>

Example Cases

  • If you want to run a task every 5 minutes, you would set it like: recurse="true" time="00:05:00"
  • If you want to run a task at 12am everyday, you would set it like: recurse="false" time="12:00:00"

It's possible to have the same piece of code run has two (or more) threads, if you configure like this:

one thread with name="ThreadThatTrys" method="ThreadCode.GO"
and other with name="ThreadThatTrysAgain" method="ThreadCode.GO"
You give them different names, but give them the same method. In this case, take into consideration that you may have to sync the access to the used resources.

Notes on the Thread Configuration

  • enable: Self explanatory
  • runonstart: If true, the thread will run when the service is started, if false, it will wait for the designated time to run
  • recurse: If true, the time value will be the wait period between the thread exits and get started again. If false, time is an absolute value indicating the time of day for the thread to run. The same Thread will never start if the previous run has not ended yet.
  • name: Name of the thread, this will be used to give a name to the log files, and identify the error mails.
  • method: The C# method that will be started, and that receives the AppThreadStruct representing the thread
  • workingFolder: This is accessible in the AppThreadStruct and can be used to provide the thread with a disk or network path where it should take care of its business.

One Thread has the Following Base Template

using System;
using System.Threading;
using XwServiceBaseSrv;

class Thread1
{
    public void GO(AppThreadStruct thread)
    {
        try
        {
            Srv.LogThread(LogLevel.Debug1, thread.Settings, "STARTING...", null, false);

            /*
	    Some useful properties

	    thread.StopRequested;
	    thread.Settings.Name;
	    thread.Settings.Time;
	    thread.Settings.WorkingFolder;
	    */

            //YOUR CODE HERE!

            Srv.LogThread(LogLevel.Debug1, thread.Settings, "...DONE!", null, false);
        }
        catch (Exception ex)
        {
            Srv.LogThread(LogLevel.Error, thread.Settings, "GO", ex, false);
        }
    }
}

The AppThreadStruct has some useful properties, but I will highlight “StopRequest”.

StopRequest” will be signalled if the service is asked to stop, so this is extremely important to check inside your long cycles in order to break out of them. If you don’t, you will end up with a service that takes ages to stop and you will find yourself using Task Manager to kill the service unnecessarily.

Using the Project

As I mentioned before, when I want to create a new service, I just copy the project, and rename it. Not a glamorous solution, but it works. I rename the solution and project files, open them with a text editor and rename the appropriate strings. Very easy as you most certainly know.

There are however some strings on the code itself that you must change, and those are the ones that identify the service to the “Windows service manager”. You will find these strings close to the beginning of file Service.cs:

static string sServiceName = "XwServiceBase"; //no spaces
static string sServiceDisplayName = "XWega Service Base";
static string sServiceDescription =
   "Generic service to use has template for Windows Services";

Future Updates

  • Any future big releases will be updated on CodeProject
  • Any future small updates will be at XWega Tools

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Max Santos
Software Developer
Portugal Portugal
No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralA few comments Pin
Pete O'Hanlon21-Nov-10 10:56
mvpPete O'Hanlon21-Nov-10 10:56 
GeneralRe: A few comments Pin
Max Santos21-Nov-10 14:25
memberMax Santos21-Nov-10 14:25 
GeneralProblem with uninstall running service Pin
mjedvidek21-Nov-10 8:53
membermjedvidek21-Nov-10 8:53 
GeneralRe: Problem with uninstall running service Pin
Max Santos21-Nov-10 10:09
memberMax Santos21-Nov-10 10:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150819.1 | Last Updated 21 Nov 2010
Article Copyright 2010 by Max Santos
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid