Learn How to Create Dual Mode Windows Services

Introduction

Windows Services provides a great way to run processes continuously in the background; however, debugging them can sometimes be a challenge.  The debugging problem is exaggerated when you have startup issues.  This can be easily solved by creating a dual mode service.  A dual mode service can run as either a Windows Service or as a console application.  To get started we first create a standard Windows Service project in Microsoft Visual Studio as shown below:


Figure 1 - Project Type

After creating the basic Windows Service project it is a good idea to create a single class which is used to startup and shutdown.  Generally, I recommend using the Constructor for startup and the Dispose method for shutdown and cleanup.  This class which I usually call manager is the initial launching point for the application.  All other threads, timers, objects, etc will need to be launched from this class.  This is important since we will be using this class to start the app in both modes.  Listed below is a simple manager class which creates a single thread timer to perform work once per second. 

  class manager : IDisposable 
  { 
     private Timer tmrWork; 
     
     public manager() 
     { 
        tmrWork = new Timer(new TimerCallback(tmrHit), null, 1000, 1000); 
     } 
  
     private void tmrHit(object state) 
     { 
        Console.WriteLine("Timer Hit!"); 
        //Perform Work Here ... 
     } 
  
     public void Dispose() 
     { 
        tmrWork.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); 
        tmrWork.Dispose(); 
     } 
  }

Next we will need to modify the Service1.cs class created in the project to actually use the manager class and start/stop the service.  You will want to create a private member variable of type manager and create the object in the OnStart method and Dispose of it in the OnStop method as shown below.

  private manager mgr = null; 
  
  protected override void OnStart(string[] args) 
  { 
     mgr = new manager(); 
  } 
  
  protected override void OnStop() 
  {{ 
    mgr.Dispose(); 
  }

The basic service itself is almost done minus the install class.  As you may know the install class is used to add the service to the Windows Service Manager during the install process.  I've included the one below for reference.

  [RunInstaller(true)] 
  public partial class Installer1 : Installer 
  { 
     private ServiceInstaller serviceInstaller1; 
     private ServiceProcessInstaller processInstaller; 
  
     public Installer1() 
     { 
        processInstaller = new ServiceProcessInstaller(); 
        serviceInstaller1 = new ServiceInstaller(); 
        processInstaller.Account = ServiceAccount.LocalSystem; 
        serviceInstaller1.StartType = ServiceStartMode.Manual; 
        serviceInstaller1.ServiceName = "Dual Mode Service 1"; 
        Installers.Add(serviceInstaller1); Installers.Add(processInstaller); 
     } 
  }

At this point you can create a Setup Project and add the project output to the custom actions for install and uninstall and this service is ready to go; however, at this point it is not able to be run as a console app.  In fact if you do it will simply give an error message stating that it cannot be run outside of Service Manager.  To solve this problem we need to make a couple changes. First we need to change the Output Type under Project Properties from Windows Application to Console Application as shown below:


Figure 2 - Output Type

Next, we need to modify the Main method in the program.cs class to correctly start up in console mode.  To support both modes, the Main method will need to accept a command line parameter which will be used to determine which mode to start in.  For this example, the code expects to see zero parameters for service mode and one for console mode.  The snippet below shows how to modify the Main to accomplish this task.

  static void Main(string[] args) 
  { 
     if (args.Count() == 0) 
     {
         //Service Mode 
        ServiceBase[] ServicesToRun; 
        ServicesToRun = new ServiceBase[] 
        { 
           new Service1() 
        }; 
  
        ServiceBase.Run(ServicesToRun); 
     } 
     else 
     { 
        //Console Mode 
        manager mgr = new manager(); 
  
        Console.ReadLine(); 
  
        mgr.Dispose(); 
     } 
  }

In the first half of the if statement, the code used to run as a service is unmodified.  The else side creates a new manager class which launches the process, keeps it running by a Console.ReadLine();  and cleans up when the user presses Enter.  To debug in console mode, it is as simple as adding a command line parameter to the Debug\command line arguments option in the project properties.

Conclusion

The method for creating a dual mode service simplifys the process of debugging; however, it will not be able to completely eliminate the need for testing as a Windows Service.  You should also determine if you actually need console mode to be deployed in the final product.  If you do not want console mode to be used outside of development, then you should use conditional compile statements or a command line password.  In addition it is a good idea to adapt common routines such as logging which can provide console output in console mode and another type of loggin service mode.

Click here to download the project example.

About the Author

Chris Bennett with Crowe Horwath LLP in the Indianapolis office. He can be reached at chris .bennett@crowehorwath.com>



About the Author

Chris Bennett

Chris Bennett is a Manager with Crowe Horwath LLP in the Indianapolis office. He can be reached at chris.bennett@crowehorwath.com.

Downloads

Comments

  • Great Article - 2 days late!

    Posted by boboliak on 02/09/2010 12:38pm

    Hey Chris, Great article. I wish it had been posted 2 days ago when I had to figure all most of this out myself. I did it in VS2010 Express Beta 2 which has no service project template, so it started as a console application and did not require modification to the output type. Thanks for posting this article!

    • Thanks

      Posted by CBennett on 02/16/2010 10:01am

      Glad you like the article.

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • It's hardly surprising that half of small businesses fail within the first 1-5 years. It's not easy to launch a new product, single-handedly manage everything from IT to accounting, fend off the competition, and grow a customer base – all at the same time – even with a great concept. Offering awesome customer service can make the difference between a startup that flies and a startup that dies. Read this white paper to learn nine ways customer support can help you beat the competition and grow your …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds