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

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Email is the most common communication vehicle used by organizations of all shapes and sizes. Among the billions of email messages sent every day are sensitive information, critical requests, and other essential business data. IT staff bear the burden of ensuring the confidentiality, integrity, and availability of the information contained within the communication. This white paper explores the email security landscape, an assessment of the threats organizations face,  and the building blocks of an effective …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds