Showing posts with label Windows Service. Show all posts
Showing posts with label Windows Service. Show all posts

Thursday, March 28, 2013

Run Multiple Tasks in a Windows Service

ServicesBase.Run(ServiceBase[] services) ...that sure made me think you could run multiple implementations of ServiceBase in a single Windows Service; but that is not how it works.

One Service, Multiple Tasks

I often have a very simple use case: I needed to run multiple tasks in a single windows service. For example, one task to poll some email notifications, and one task to listen to HTTP requests that might trigger those same notifications.

I like the basic setup of OnStart, Run, and OnStop, but after authoring several windows services I got tired of writing the same code over and over again. Thus I created the WindowServiceTasks library. Now whenever I need to do another task in a service, I just implement the WindowsServiceTaskBase or WindowsServiceLoopBase class, and my code is all ready to go!

WindowsServiceTasks

Run multiple tasks in a single WindowsService, and let the base library do all of the work setup and tear down for you. The WindowsServiceTasks NuGet package is simple, flexible, and extremely light weight.

Example

public static class Program
{
    public static void Main(params string[] args)
    {
        var logger = new Logger("Demo.log");
        var emailTask = new EmailServiceTask(logger);
        var failTask = new FailServiceTask(logger);
 
        var service = new Service1(logger, emailTask, failTask);
        service.Start(args);
    }
}
public class EmailServiceTask : WindowsServiceLoopBase
{
    private readonly ILogger _logger;
 
    public EmailServiceTask(ILogger logger)
    {
        _logger = logger;
    }
 
    protected override int LoopMilliseconds
    {
        get { return 2000; }
    }
 
    protected override void HandleException(Exception exception)
    {
        _logger.Log(exception);
    }
 
    protected override void RunLoop()
    {
        // TODO Send Email!
        _logger.Log("EmailServiceTask.RunLoop - Sending an email");
    }
 
    public override void OnStart(string[] args)
    {
        _logger.Log("EmailServiceTask.OnStart");
    }
 
    public override void OnStop()
    {
        _logger.Log("EmailServiceTask.OnStop");
    }
 
    protected override void DisposeResources()
    {
    }
}
Shout it

Enjoy,
Tom

Thursday, February 28, 2013

Running a Windows Service as a Console App

This is a prerequisite post before I can talk about the WindowsServiceTasks library that I recently released.

How do you test windows services?

I hope your first response was unit tests, but even if it was we both know that you still have to integration test the whole application. You could install your service into windows and then attach your debugger to it's process, but that is a lot of work. Why not just run your service as a console application? Then you can test it by just pressing play in Visual Studio!

How do you run a windows service as a console application?

Easy! Just go into your windows service project's settings and set the Output Type to Console Application. This will allow the executable to launch as a console app, but it is still completely executable as a service!

Inside of your code, you can use the Environment.UserInteractive property to determine which mode you are in. With that you can do cool things to help you debug, such as register an alternate logger with your IOC container that will write your long lines to console instead of (or as well as) to file.

static class Program
{
    static void Main(params string[] args)
    {
        var service = new Service1();
 
        if (!Environment.UserInteractive)
        {
            var servicesToRun = new ServiceBase[] { service };
            ServiceBase.Run(servicesToRun);
            return;
        }
 
        Console.WriteLine("Running as a Console Application");
        Console.WriteLine(" 1. Run Service");
        Console.WriteLine(" 2. Other Option");
        Console.WriteLine(" 3. Exit");
        Console.Write("Enter Option: ");
        var input = Console.ReadLine();
 
        switch (input)
        {
            case "1":
                service.Start(args);
                Console.WriteLine("Running Service - Press Enter To Exit");
                Console.ReadLine();
                break;
 
            case "2":
                // TODO!
                break;
        }
 
        Console.WriteLine("Closing");
    }
}
 
public partial class Service1 : ServiceBase
{
    public Service1() { InitializeComponent(); }
 
    public void Start(string[] args) { OnStart(args); }
 
    protected override void OnStart(string[] args) { }
 
    protected override void OnStop() { }
}

What other uses does this offer?

You can then also use your windows services as management utilities. I have worked with applications before where when I needed to make a configuration change to a system I was told to go run windows services with random undiscoverable command line arguments or magic number configuration settings. By launching your service as a console app you can inject simple menu systems to allow users easy access to admin functionality.

Shout it

Enjoy,
Tom

Real Time Web Analytics