Debuggable Self-Host Windows Service Projects

When developing self-hosted WCF services, you really need two things:

  1. A windows service project that will be the host for the deployed environment.
  2. A console self-host project for easy debugging while developing the service.

Yes, there is also the option to use a WCF Service Library project with its associated WcfServiceHost.exe process that self hosts the service for debugging. However, I have run into too many occasions where something is going wrong and not having direct access to the hosting code wastes more cycles than it takes to set up my own service host, so other than quick demos, I never use the WcfServiceHost.exe in production development.

Having two separate projects to address 1 & 2 above is not really that great either, but if you try to run a service project in the debugger, you get an error telling you it can only be run through the services panel in Windows.

However, through a quick and easy pattern, you can make your service projects so they run as a console for development, but run as a service just fine when installed.

Step 1: Create a Windows Service project for the self host environment.

This is just the standard selection in the project dialog for a Windows Service project. Once you have your service class, rename it as appropriate and right click on the designer surface to add an installer class for the service. Standard stuff here.

Step 2: Implement your hosting code in a separate class from the service class itself.

For example, here is a very simple hosting class that can be used for any service in any project (with some appropriate exception handling and logging added in for production purposes):

publicclass SelfHost { ServiceHost mHost; publicvoid Start() { mHost = new ServiceHost(typeof(T)); mHost.Open(); } publicvoid Stop() { mHost.Close(); } }

From the service class itself, you can just instantiate an this class and call its Start and Stop methods. publicpartialclass SimpleServiceHostService : ServiceBase { SelfHost m_Host = new SelfHost(); public SimpleServiceHostService() { InitializeComponent(); } protectedoverridevoid OnStart(string[] args) { m_Host.Start(); } protectedoverridevoid OnStop() { m_Host.Stop(); } }

Now when you install this service, the service host will be started and stopped through the services panel or automatically depending on the service configuration.

Step 3: Modify the Main method to start conditionally as a Console or a service.

Modify the default main declaration with no parameter to the signature for a main that takes a string[] of arguments. If arguments are present, run the code as if you are in a console app. If no arguments, call the default code for starting it as a service. For the console host mode, just call the Start and Stop methods on an instance of your host class just like the windows service did.

staticvoid Main(string[] args) { // Run as console if there are command line argumentsif (args.Length > 0) { SelfHost host = new SelfHost(); host.Start(); Console.WriteLine("Press Enter to Exit..."); Console.ReadLine(); host.Stop(); } else// run as service { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new SimpleServiceHostService() }; ServiceBase.Run(ServicesToRun); } }



Step 4: Modify the project properties to be a console application and add a debug command line parameter.

ApplicationType

DebugOptions

That is basically it. Change the code shown above to use your service type, add an app.config with the appropriate WCF service code, and you are ready to run as a console app in the debugger, but when you build and install your service as a service, it will run fine as that as well.

You can download a full sample application here.