Create a Windows Service in .NET That Can Also Run as Console Application

Date Published: 13 April 2011

Create a Windows Service in .NET That Can Also Run as Console Application

I’m creating a simple windows service using Visual Studio 2010 and .NET 4. I want to be able to easily test it by simply running the resulting exe without the need to install the service. I did some research on this topic and found three helpful articles:

I found that the first article was a bit more work than the second. In the end, I pretty much combined the latter two articles’ approaches and created a simple template (in C#) that can be used as a starting point for any long-running windows service. It’s still a work in progress, but I figure this will probably give some folks a head start and also is an opportunity for folks to tell me what I’m doing wrong.

To start, create a new Windows Service Project:

Once that’s done, you should have a Program.cs and a Service1.cs file in your project. You can delete the Program.cs file. Edit the Service1.cs file as follows:

using System; 
using System.Diagnostics; 
using System.ServiceProcess; 
using System.Threading; 
using System.Timers; 
using Timer = System.Timers.Timer; 

namespace  ScheduleService 
{ 
    public partial class ScheduleService : ServiceBase 
    { 
        private static readonly object lockobject =  new object(); 
        private  Timer _timer; 
 
        public ScheduleService() 
        { 
           InitializeComponent(); 
        } 
 
        private static void Main(string[] args) 
        { 
             var service = new ScheduleService(); 
             if  (Environment.UserInteractive) 
             { 
                 service.OnStart(args); 
                 Console.WriteLine("Press any key to stop the program"); 
                 Console.Read(); 
                 service.OnStop(); 
             } 
              else  
             { 
                 Run(service); 
             } 
         } 
 
         protected override void OnStart(string[] args) 
         {
             _timer = new Timer(); 
             _timer.Enabled =  true ;  // call the Elapsed event  
             _timer.Interval = 5000;  // in milliseconds  
             _timer.AutoReset =  true ;  // keep calling elapsed method.  
             _timer.Elapsed += _timer_Elapsed; 
             _timer.Start(); 
         } 
 
         private void _timer_Elapsed(object  sender, ElapsedEventArgs e) 
         { 
              lock  (lockobject) 
             { 
                 _timer.Stop(); 
                 ExecuteStep(); 
                 _timer.Start(); 
             } 
         } 
 
         private void ExecuteStep() 
         { 
             Debug.Print("Executing..."); 
             Thread.Sleep(1000); 
             Debug.Print("Done."); 
         }

          protected override void OnStop() 
         { 
         } 
 
     } 
 
 } 

You’ll also want to rename the ServiceName property, which you can access from the Designer View of the ScheduleService.cs class (or Service1.cs if you haven’t renamed it yet).

If you run this without doing anything else, you will most likely get an error telling you that you have to install the service. The last bit you need to do is change your project properties to Console Application.

Once that’s done, you should be able to run the resulting EXE, and you will see a simple console window appear, saying “Press any key to stop the program”. Also, if you use a tool like DbgView from SysInternals to watch your debug output, you will see something like this:

A couple of things to note here:

  • My service doesn’t kick off every 5 seconds.
  • It kicks off 5 seconds after the last time it ran. This is important because if I have more than 5 seconds of work to do, I don’t want two instances of my service running simultaneously and stepping on one another.

For my specific use case, it’s very likely that when there is something to do, it will take much longer than 5 seconds to do it, but I don’t want my interval between checking for work to be longer than 5 seconds, so this works very well. If your requirements are different, and you absolutely need your service to do something at specific fixed intervals, then you’ll want to revise this design, and perhaps consider looking into something like Quartz to manage the scheduling aspect of your needs.

Steve Smith

About Ardalis

Software Engineer

Steve is an experienced software architect and trainer, focusing currently on ASP.NET Core and Domain-Driven Design.


Ardalis

Copyright © 2020