Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Host WCF as Windows Service without Installing

, 5 Dec 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Learn how to host WCF as a Windows service (without using a web project) and how to code it so that you can test interactively without installing the service.

I am working on a project that involves a centralized UI that then coordinates with agents to send out instructions. The agents will be WCF endpoints and to ease deployment/minimize the install footprint, they will install as windows services with a nice installer rather than hanging onto an IIS webspace directly.

In this post I want to walk you through the process of creating that WCF host programmatically, as well as a small little tweak that will allow you to run and test without having to install the service. It's actually quite easy to do but it's one of those things that can produce an "ah-hah!" moment if you haven't done it before.

To start with, let's create a simple service and operation contract. Create a new interface, call it IHelloWorldService, and add a method, like this:

[ServiceContract(Namespace="http://wintellect.com/sample")]
public interface IHelloWorldService
{
    [OperationContract]
    [FaultContract(typeof(Exception))]
    string Hi();
}

You'll have to add references and usings for System.ServiceModel.

Next, implement the interface:

public class HelloWorldService : IHelloWorldService
{
    const string REPLY = "Hello, world."; 

    public string Hi()
    {
        return REPLY; 
    }

}

That's all it takes to make your WCF service. Now we just need a way to host it. Add another reference to System.ServiceProcess. Create a new class called HelloServiceHost and derive it from ServiceBase. Now we'll get a little interesting:

public class HelloServiceHost : ServiceBase
{
    const string CONSOLE = "console";

    public const string NAME = "HelloWorldService"; 

    ServiceHost _serviceHost = null;

    public HelloServiceHost()
    {
        ServiceName = NAME; 
    }

    public static void Main(string[] args)
    {
        if (args.Length == 1 && args[0].Equals(CONSOLE))
        {
            new HelloServiceHost().ConsoleRun();
        }
        else
        {
            ServiceBase.Run(new HelloServiceHost());
        }
    }

    private void ConsoleRun()
    {
        Console.WriteLine(string.Format("{0}::starting...",GetType().FullName));

        OnStart(null);

        Console.WriteLine(string.Format("{0}::ready (ENTER to exit)", GetType().FullName));
        Console.ReadLine();

        OnStop();

        Console.WriteLine(string.Format("{0}::stopped", GetType().FullName));
    }

    protected override void OnStart(string[] args)
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
        }

        _serviceHost = new ServiceHost(typeof(HelloWorldService));
        _serviceHost.Open();
    }

    protected override void OnStop()
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
            _serviceHost = null;
        }
    }
}

Let's break it down. We're derived from service base, and need a service host to actually present the WCF end point. In the constructor, we set the service name. In the Main class, which is called for both console applications and service applications, we check the arguments. If you pass in "console" as an argument, it will create a new instance and run it directly. Otherwise, it calls into the ServiceBase to run as a Windows service.

The ConsoleRun is stubbed out to give you a nice message that it is starting, then manually call the start event and wait for a line to be entered. When you hit ENTER, it will close the service and shut down. This is what enables us to take the generated executable, and call it, like:
HelloWorldService.exe console
and then debug interactively without having to install it as an actual service.

The OnStart and OnStop overrides do basic housekeeping for registering the types of the endpoints that will be active (this one process could host several endpoints, if you so desired) and shutting down when finished.

Of course, you'll need to add an app.config file and come up with your end point name. It can run on existing IIS ports, but must have a unique URL. I set mine up like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="HelloWorldService.HelloWorldService" behaviorConfiguration="HelloWorldServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:80/helloworld"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="HelloWorldService.IHelloWorldService"/>
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloWorldServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Once this is in place, you should be able to compile, browse to the directory it is in, and run the program with the "console" argument (no dashes or anything special). Once it is waiting for a keypress, go to a web browser and navigate to http://localhost/helloworld?wsdl and you should see the WSDL for your service. At this point you could hook it up to a test harness, use SoapUI, or about any other method for testing and start doing things with the service.

Of course, eventually the goal is to allow it to be installed as a Windows service. For that, add a reference to System.Configuration.Install. Add a new class and call it ProjectInstaller. Derive the class from Installer. The class will look like this:

[RunInstaller(true)]
public class ProjectInstaller : Installer
{
    const string DESCRIPTION = "Hello world service host.";
    const string DISPLAY_NAME = "Hello World Service";

    private ServiceProcessInstaller _process;
    
    private ServiceInstaller _service;

    public ProjectInstaller()
    {
        _process = new ServiceProcessInstaller();
        _process.Account = ServiceAccount.LocalSystem;
        _service = new ServiceInstaller();
        _service.ServiceName = HelloWorldService.NAME;
        _service.Description = DESCRIPTION;
        _service.DisplayName = DISPLAY_NAME; 
        Installers.Add(_process);
        Installers.Add(_service);
    }
}

Now you can navigate to the command line and use installutil.exe to install it as a bona fide Windows service.

I'm not including a demo project because this should be fairly straightforward and I've included 100% of the code in this post ... I bet you might not have known hosting a WCF service outside of an actual web project was so simple!

Jeremy Likness

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jeremy Likness
Architect Wintellect
United States United States
Jeremy Likness is a principal consultant at Wintellect. Jeremy, an experienced entrepreneur and technology executive, has successfully helped ship commercial enterprise software for 20 years. He specializes in catalyzing growth, developing ideas and creating value through delivering software in technical enterprises. His roles as business owner, technology executive and hands-on developer provided unique opportunities to directly impact the bottom line of multiple businesses by helping them grow and increase their organizational capacity while improving operational efficiency. He has worked with several initially small companies like Manhattan Associates and AirWatch before they grew large and experienced their transition from good to great while helping direct vision and strategy to embrace changing technology and markets. Jeremy is capable of quickly adapting to new paradigms and helps technology teams endure change by providing strong leadership, working with team members “in the trenches” and mentoring them in the soft skills that are key for engineers to bridge the gap between business and technology.
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
GeneralMy vote of 4 Pinmemberrajeev010324-Apr-13 2:02 
Questionnice. PinmemberManas Bhardwaj2-Jun-12 6:04 
GeneralHelpfull PinmemberEric Bogaerts9-Dec-09 10:05 
Nice to test services and you give insight by your cleanly written article.
GeneralNice Article.,. PinmemberSrinath G Nath8-Dec-09 17:24 
GeneralVery nice PinmemberPeterFortuin8-Dec-09 5:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 5 Dec 2009
Article Copyright 2009 by Jeremy Likness
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid