Windows Service Template

Every time I write a windows service I have to go through the process of creating mostly the same code which always end up looking allot like the code below, so figured I would publish it here for future reference and possibly help someone else with the same problem.

A quick rundown of what's happening below:

I generally use the Visual Studio Templates to create a new Windows Service project which basically puts the using statements you see below into a new class, implements the OnStart and OnStop methods of the ServiceBase interface and leaves you there. (I'm not going to cover the addition of installers etc., as there is loads of help elsewhere on the web for that).

The Windows Services console allows a service something like 32 seconds to complete start-up. If it doesn't, it will report that the service could not start successfully. This obviously means that you cannot put your main program code into the OnStart (or any synchronously called method). That's why I kick off a new Thread, allowing the OnStart method to complete, and allow the Services Console to report success.

The Run and Running Boolean variables allow me to manage the worker thread when a user selects to stop the service, allowing the running worker process time to complete its current cycle, before ending (Provided this cycle can end if a configured amount of time anyway).

About the debug argument:

If you right click on an installed service and select Properties, you get a similar screen to the one below. Anything you type into the Start parameters textbox is passed to your service as arguments.

If the code below receives an argument of "debug" the code causes the thread to sleep for 20 seconds before continuing execution as normal. This means that if a developer adds a breakpoint just after the Thread Sleep command, he/she has 20 seconds to attach the debugger to the service process after he has started the service. When the Thread Sleep expires, Visual Studio should stop at your breakpoint, allowing you to step through your code at will.

The code can be left as is for the final production system since it would be skipped over unless someone adds a "debug" parameter, and even then, the start-up will only be delayed by 20 seconds.

Let me know if you have found this useful or if you have any better suggestions. ;-)

Note: To leave comments, you have to log in at the bottom of the screen with your Google account.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.Linq;

using System.ServiceProcess;

using System.Text;

using System.Threading;

namespace Gineer

{

public partial class Host : ServiceBase

{

public Host()

{

InitializeComponent();

}

private Boolean Run = false;

private Boolean Running = false;

private Thread workerThread = null;

protected override void OnStart(string[] args)

{

Boolean Debug = false;

if (args != null)

{

foreach (String arg in args)

{

if (arg.ToLower() == "debug")

{

Debug = true;

}

}

}

workerThread = new Thread(Worker);

workerThread.Start(Debug);

Thread.Sleep(100);

}

protected override void OnStop()

{

DateTime StartedWaiting = DateTime.Now;

TimeSpan WaitLimit = new TimeSpan(0, 0, 45); //Value should be configurable

Run = false;

while (Running)

{

Thread.Sleep(500);

//wait for the thread to complete it's current process

if (DateTime.Now.Subtract(StartedWaiting) > WaitLimit)

break;

}

if (workerThread != null)

{

workerThread.Abort();

workerThread.Join();

}

}

private void Worker(Object State)

{

Boolean Debug = (Boolean)State;

if (Debug)

{

/*

* Give a developer 20 seconds to attach a debugger if we are in

* Debug mode.

*/

Thread.Sleep(new TimeSpan(0, 0, 20));

}

while (Run)

{

Running = true;

//Do work...

Thread.Sleep(new TimeSpan(0, 0, 30)); //Value should be configurable

}

Running = false;

}

}

}