Hosting a WCF service in a Windows Service

In my last post I explained how you could use WCF and MSMQ to respond to messages asynchronously. We’ve setup a class library with our service, a console application for our host and a console application for our client. In this post I’ll explain how we can use the class library again for hosting our WCF service in a Windows Service.

1: Add the Windows Service

Add a new Windows Service project. Right-click the solution, choose “Add” -> “New Project…” and select “Windows” from the tree on the left. Then select “Windows Service” from the project templates. Call it “MailServiceHost” for example. It’ll create the project with a file (class) called ‘Service1.cs”. Rename it to ‘MailService.cs’ using the solution explorer.

2: Implement OnStart and OnStop methods

When you look into your MailService class, you’ll see that it’s derived from ServiceBase and that two methods are already defined. We’ll first implement the OnStart method. Here we’ll do exactly the same as in the console application created in the previous article.

  1. Create the message-queue of it does not exist yet.
  2. Create and open the ServiceHost

The only difference now is that it’s a private member variable (defined on class level) because the OnStop method must have access to it as well.

ServiceHost _host = null;

protected override void OnStart(string[] args)
{
  string queueName = ConfigurationManager.AppSettings["SendMailQueueName"];

  Trace.WriteLine("Starting Class-A E-mail Service...");

  if (!MessageQueue.Exists(queueName))
  {
    Trace.WriteLine("Creating queue : " + queueName);
    MessageQueue.Create(queueName, true);
  }

  _host = new ServiceHost(typeof(SendMailService));
  _host.Open();
}

Here’s a quick overview

  • Line 1 declares the ServiceHost as member variable.
  • Line 5 retrieves the queue name from your configuration file.
  • Line 9 & 12 create the queue if it doesn’t exist yet.
  • Line 15 & 16 instantiate and open the host.
  • I’ve also added a few trace messages. The easiest way to see these is to get DebugView from SysInternals.

Now we have to implement the OnStop method.

protected override void OnStop()
{
  Trace.WriteLine("Shutting down Class-A E-mail Service...");
  if (_host != null)
  {
    _host.Close();
    _host = null;
  }
}

Note that the above code does not do any error handling or check if the ServiceHost its state is actually open, etc, etc.

3: Configuration

Now we have to add configuration. Add a new Application Configuration file and just copy & paste the entire configuration file from our previous Console Application host project.

4: ProjectInstaller

We’ve created our service, but aren’t done yet. For Windows Services it’s best if you add a ProjectInstaller so the service can easily be installed. Choose to add a new item to the project and select the “General” category and then the “Installer Class” template.

[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
  public ProjectInstaller()
  {
    InitializeComponent();
    ServiceProcessInstaller processInstaller= new ServiceProcessInstaller();
    ServiceInstaller serviceInstaller = new ServiceInstaller();
    processInstaller.Account = ServiceAccount.LocalSystem;
    serviceInstaller.StartType = ServiceStartMode.Automatic;
    serviceInstaller.ServiceName = "Class-A E-Mail MSMQ Service";
    Installers.Add(serviceInstaller);
    Installers.Add(processInstaller);
  }
}

In the above code we’ve added a ServiceProcessInstaller and a ServiceInstaller. The ServiceProcessInstaller is used by InstallUtil.exe and we’re using it to specify that we want to use the Local System account to run our service. If you specify ServiceAccount.User and don’t provide a username and password, it’ll request these during installation of the service. With the ServiceInstaller we’re specifying that our service has to start automatically on Windows startup and the name of our service.

That’s it, our WCF service is now running inside a Windows (Managed) Service.

Download the solutionΒ for a complete view on what we’ve done.

You may also like...

52 Responses

  1. Mike says:

    Hi,

    Is this deployable to other computers? (other than your own dev computer?)

    If not, how would a deployable Windows Service be made?

    Thanks.
    Cheers,
    Mike

  2. Yes, this should be deployable on any machine running .NET Framework 3.0

  3. Morgan says:

    Hi Dennis,
    Your articles look good. Your zip file for this project seems to be corrupt or the upload was broken. Could you please upload again? Cheers

  4. HANK says:

    I have my WCF service hosting in Windows Service as well but I have the problem If I install the WCF service in diferent server where the client is (Sharepoint 2007) this stop to work and I get the error :”The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was ’00:00:59.9843750′.=>The write operation failed, see inner exception.”

    I am not sure is timeout because I incresea to 10 hrs and still I get the same error.

    The other problem that I have is with the auto-disconnect feature in WCF. If the user has the ASPX form Open for more than the time define the WCF server stop to work and I have to reset the IIS.

    Do you have some idea??

    Regards
    HANK

  5. Akhil Jadhav says:

    Can you tell me. Why my service is going in faulted state? I have implemented IErrorHandler to handle the service and restart the service when reciveretry count exhaust(and when service goes in faulted state). can you suggest me why when my service is goes in faulted state even after restarting the service service is not picking the next message.

    Please reply me.

  6. charlie says:

    I implemented a solution similar to yours but I’ve run into an issue. Everything works OK except when OnStop is called, the _host variable is always null. It seems the class derived from ServiceBase doesn’t maintain state. I don’t know if the service is being shut down and cleaned up properly.

  7. Dennis van der Stelt says:

    The only thing I can think off immediately, is that you’re using the “using” keyword. As in:

    using (ServiceHost host… )
    {
    }

    At the closing } the .Dispose() method is called and your ServiceHost is closed. Loose the using statement.

  8. kakalot says:

    Hello Dennis Van der Stelt,
    I have a question to ask you? I have a program, window application, And I want my program can communication together in different computers. I can use tcp/udp, socket in .net 2.0. However, I would like to use new technique WCF. So, Can you tell me more about WCF in this situation? I hope to hear from you.
    thanks

  9. Dennis van der Stelt says:

    @kakalot : That’s a really, really long story… But basically…

    If they’re in the same domain, use nettcp and windows authentication because it’s fast and easy.

    If Windows Authantication isn’t available, but you do need security, go for X509

    If you can’t use TCP/IP for some reason (firewalls, nat, etc) you might want to try out .NET Services with its service bus. BizTalk Services is ‘t predecessor and probably still running.

    Most of the time, port 80 is open and you’ll be able to use wsHttpBinding.

    But that’s not all… Do you need duplex? Do you need peer-2-peer? It depends on a lot of stuff waht’s the best binding and such for you.

  10. kakalot says:

    Dear Dennis Van der Stelt,
    Thank you very much for your sharing. If you have free time, I hope you tell more detail about: When we should use nettcp, when we should use WCF and what are different between them. I think It is the interesting topic which a lot of people would like to discuss.

  11. casino gambling forum says:

    Thanks ofr the article. I had a question regarding the best practice in my scenario. We have a WCF service that needs to expose basicHttp and Tcp binding. Would it be best to have both bindings exposed by hosting in a Windows Service Or should we host the basic http binding in IIS and only the NetTCPBinding as Windows Service?

  12. Dennis van der Stelt says:

    Hi Casino Gabling Forum,

    First, I have removed the link to your website. Second, if you really want an answer to that question, please repost it, without a link to some stupid gambling site and with a normal name.

    Thanks! πŸ™‚

  13. Twonne says:

    Hi Dennis!

    We’re hosting a WCF service, with NetMsmqBinding (3.0) inside a windows service. When a poisonMessageException occurs, we want to remove the poison message to an errorqueue and restart the WCF service, because it’s in a faulted state. We tried two different scenarios, but we’re having troubles on both of them. Maybe you can help us?

    This is our solution structure (in test):

    OrderValidatorHost (Windows Service Installer, Hosting WCF service)
    OrderValidatorService (Contract + Implementation)
    ServiceHelper (PoisonErrorHandler.cs)

    Our 1st attempt:

    Custom errorhandler: http://msdn.microsoft.com/en-us/library/ms751472.aspx

    Everything in this sample works, except for this step:

    static WaitCallback orderProcessingCallback = new WaitCallback(OrderProcessorService.StartThreadProc);

    In the Microsoft example, everything is in one solution. Our solution is devided into seperate projects. The Host has a reference to the Service; the Service has a reference to the ServiceHelper (for errorhandler). Now we should need a reference from our ServiceHelper to our Service Host (Windows Service), this for making the WaitCallback. This is not possible because we would have then a circular dependency… Any idea to work this around?

    Our 2nd attempt:

    2. We add an eventhandler to our Windows Service to be triggered when the WCF host becomes faulted:

    protected override void OnStart(string[] args)

    {
    host = new ServiceHost(typeof(OrderValidator));

    host.Open();

    ((ICommunicationObject)host).Faulted += new EventHandler(OnServiceFaulted);

    }

    private void OnServiceFaulted(object sender, EventArgs e)

    {

    //The problem here is that we can’t find a way to retrieve the message ID (the queue look up ID) of the poison message, to remove that message to our errorqueue

    ((ICommunicationObject)sender).Abort();

    host = new ServiceHost(typeof(OrderValidator));

    host.Open();

    }

    Any suggestion to catch de MsmqPoisonMessageException in this EventHandler?

    Thanx a lot for your time!

    }

    Dit lijkt ons ook een mogelijkheid, maar we zien niet hoe het haalbaar is om de msmqpoisonmessageexception op te vangen. Is de mogelijk?

  14. Alex says:

    I have three wcf services hosted in window service.I need to host these three services, so i prepare one common setup of these three services by adding Primary Output.
    Is there any other way i can achieve the same like comon location so that all DLL will be pick from that location ?

  15. Rose says:

    Thanks for the article.

    I have a question – I am trying to use BasicHTTPBinding for a windows service – it will be called by a PowerBuilder 8 app, and it only understands BasicHTTPBinding.

    I tried hosting the service, but when I start it, I get the error:
    Error Starting, error: Could not find a base address that matches scheme http for the endpoint with binding MetadataExchangeHttpBinding. Registered base address schemes are [].12/9/2009 10:10:50 AM

    I do have the basicHTTPBinding and mexHTTPBinding in the config file.

    Any suggestions? Is it even possible to expose a basicHTTPBinding for a windows service?

    Thanks in advance~

  16. Dennis van der Stelt says:

    Hi Rose,

    Yes, basicHttp is possible in a Windows Service.

    The problem you have is that the MEX endpoint can’t find an address to host itself on. You need to specify the address at the MEX endpoint itself.

    If your service is at
    http://localhost/myservice/
    It’s normal to put it at
    http://localhost/myservice/mex/

    My article about WCF addresses also shows the common way to specify a base address:
    http://bloggingabout.net/blogs/dennis/archive/2006/11/29/WCF-Part-6-_3A00_-Address.aspx

  17. Kiran says:

    We have a WCF service that needs to expose basicHttp and Tcp binding. Would it be best to have both bindings exposed by hosting in a Windows Service Or should we host the basic http binding in IIS and only the NetTCPBinding as Windows Service?

  18. Dennis van der Stelt says:

    @Kiran : If you have Win2008 I’d suggest hosting them both in IIS.

    Else my answer is : it depends! πŸ™‚
    IIS is much more trustworthy for your services. If the outside world connects to HTTP and internally to TCPIP I’d probably suggest your solution. When internally the service goes down, you’ll know immediately and can probably do something about it because you’re at work.

    Of course it depends on probably more things, but I guess your suggestion will work out. I don’t see any problems in having multiple hosts, but only the deployment that will become more cumbersome.

  19. Sowmya says:

    Hi Dennis,

    I have a WCF service which I have hosted using a windows service and this windows service is created Local System log on account. I have created a private queue created for the WCF service and this queue has all the permissions required for the windows service account to access the queue. The service has been installed successfully, but when I try to run the web application which actually calls the WCF service, the following error is thrown. It works very well in the debugging environment though. Only when I run the web application by publishing it this error occurs. Also, I am trying to access the queue from the same machine.

    System.ServiceModel.CommunicationException: An error occurred while sending to the queue: No internal Message Queuing certificate exists for the user. (-1072824273, 0xc00e002f).Ensure that MSMQ is installed and running. If you are sending to a local queue, ensure the queue exists with the required access mode and authorization.

    How do I further ensure that the queue is installed and running and get rid of this error. Windows service is successfully running on the machine. Could you please let me know where am I missing?

    Thanx
    -Sowmya

  20. Dennis van der Stelt says:

    Sowmya, perhaps you should contact me privatly… Just use this page : http://bloggingabout.net/blogs/dennis/contact.aspx

  21. Sowmya says:

    Hi Dennis,

    I have sent you the issue that I am facing in WCF service using the page that you have directed me to. Could you suggest any possible solution to that issue?

    Thanx
    -Sowmya

  22. Mukund says:

    I have .net 1.1 classlibrary. I want it to use WCF hosted as a windows service. How can I do that? Is it possible?

  23. Dennis van der Stelt says:

    @Mukund : No, that’s not possible, because .NET 1.x and .NET 2.0 don’t mix together.

    If you can recompile it to .NET 2.0 you probably can, although I’m not really sure what you mean with a simple class library. If it’s just some code that you want to run once in a while, you don’t need WCF. WCF is for communication between systems or applications.

  24. I have a 3.5 WCF service that I’, hosting with Windows Service. I have security wshttpBinding mode = “none” for a prototype we’re doing. Works wonderfully locally on my box. When I deploy to a remote server on different domain I am having issues. They have the domain nat’d to an internal IP. THey have also setup the domain on an IIS site pointing to a random location on the box. Is this the way to accomplish getting to the service in a real world scenario?

    Basically what I’m getting at is how do you tell the outside world I’m hosting this service through this domain besides just the config for the service? What else has to be touched on the box? IIS?

    Thanks !

  25. Dennis van der Stelt says:

    @Santiago : Sorry for the late reply. This is exactly why the Windows Azure AppFabric ServiceBus was build. It’s hard to forward calls from an outside IP (172.138.12.14 or something) to an inside IP (like 192.168.0.12). You could have a look at routing or something.

    But why not deploy the service on the box that’s directly connected to the internet?

  26. Hisuke says:

    How about hosting a wcf service at the same time with another service in a single windows service? for example, i would like to host my wcf service everytime i start my MyOtherService? Can that be possible?

  27. Dennis van der Stelt says:

    That’s most definitely possible, you just have to take into account that QoS (Quality of Service). Your service won’t restart automatically, you’ll have to program that yourself. Also when there are attacks or memory leaks, your Windows Service won’t help you with those. IIS will!

    I can’t stress enough that IIS is the best option to host your WCF Services. Especially if you have WAS (Windows Process Activation Services) there’s almost no need to host your services yourself.

  28. Anil says:

    I am trying to host my WCF service using Windows Service. I have created the installer for that and it is installed successfully, but whenever I am trying to run the service I am getting the following error :-

    Service cannot be started. System.InvalidOperationException: Service ‘WcfService1.Service1’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
    at System.ServiceModel.Description.DispatcherBuilder.EnsureThereAreNonMexEndpoints(ServiceDescription description)
    at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
    at System.ServiceModel.ServiceHostBase.InitializeRuntime()
    at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
    at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
    at System.ServiceModel.Channels.CommunicationObject.Open()
    at WindowsServiceHostApp1.Service1.OnStart(String[] args) in C:Documents and Settingskr-ajayDesktopDemo-ProjectHost_WindowsServ…

    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

    Please help me to resolve the issue.

  29. Dennis van der Stelt says:

    Hey there,

    You forgot to configure an endpoint in your App.Config or it’s not correct.

    You can read more about it here:
    http://bloggingabout.net/blogs/dennis/archive/2006/11/09/WCF-Part-3-_3A00_-Hosting-the-service.aspx

    Or Full examples here and here:
    http://bloggingabout.net/blogs/dennis/archive/2010/06/16/wcf-simple-example-in-visual-studio-2010.aspx
    http://bloggingabout.net/blogs/dennis/archive/2007/04/20/wcf-simple-example.aspx

    You probably need something like the config below. However, I don’t know the exact types of your contract and it’s implementation.

  30. Anil says:

    Hi Dennis,

    Thanks for your quick response. here is a copy of my config file, please have a look on that and suggest me what need to be fixed.

  31. Anil says:

    Is there any Tools/ third party tools/ utility to migrate my existing web service to WCF.

    Please help me find out the migration tools.

  32. siva says:

    Hi dennis,
    I have developed WCF service concept of publisher and subscriber, here publisher to develop in WCF service library and subscriber to develop in windows application. publisher to implemented on windows application its working fine, but when i deploy the publisher in windows service to start i got error.,

    “Error opening host : HTTP could not register URL http://+:8731/WCFServerDLL/Service1/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).”
    The above link for microsoft to see to use httpcfg.exe and set the URL, before to run on windows application that time i implemented to set the URL.
    what the reason for it doesn’t work? can you give me suggestion.

  33. Dennis van der Stelt says:

    Hey Siva,

    You’re not giving a lot of information on Windows version or so. But my guess is a question of rights. Read this blog to find more info:
    http://blogs.msdn.com/b/amitlale/archive/2007/01/29/addressaccessdeniedexception-cause-and-solution.aspx

    If you find the solution in the blog difficult, try to start the service with administrator rights. Giving your Windows Service the local admin account or something. If that works, you know it’s a rights problem.

  34. siva says:

    hi dennis,
    thanks for quick response, i am using windows XP.
    The above blog as similar that this link “http://msdn.microsoft.com/en-us/library/ms733768.aspx”. i had to implement that using httpcfg.exe to set the URL.
    My user account also administrator rights already there.but i got same error

  35. siva says:

    I give my App.config File below here to check is correct.

    <!–

    –>

  36. siva says:

    hi dennis,
    i am in crucial time,pls to give me a suggstion.

  37. siva says:

    windows XP sp3.
    Here i run the httpcfg.exe set urlacl /u http://localhost:8731/WCFServerDLL/Service1/ /a

    i get the result

    HttpSetServiceConfiguration completed with 87.

  38. ahobul says:

    i hosted my wcf service in windows service but when i call async method of wcf service am getting cross-domain error as below :

    This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.

  39. Dennis van der Stelt says:

    @ahobul: Did you try a default basichttp client in a console window and got that to work cross domain?

  40. ahobul says:

    ya it is working with console application in both cases nettcp and basichttp, but it is not working with silverlight application

  41. Dennis van der Stelt says:

    @Ahobul : Silverlight isn’t allowed cross domain to access wcf services, meaning that you need a crossdomain.xml or clientaccesspolicy.xml file. As this most likely isn’t possible via a Windows Service, you probably need to put the service on a webserver.

    Read more here:
    http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx

  42. Febin says:

    Hi,

    I have a doubt regarding this. I have hosted a WCF service project in Windows service.Also I have another project file which is also using WCF services. I want to refer this Hosted WCF service in a WCF service. So how can i do that? Can you please tell the steps to do that?

    In short “Consuming Windows Service hosted WCF service from another WCF project file”

  43. lschneider says:

    Hi,
    I have a WCF duplex with TCP binding (for the speed)hosted in Windows under a domain user. then I have a client not in the domain.
    How should we configure the system to make it work?
    It works fine for the users within the domain.

  44. dst says:

    Hi Dennis,

    I have a very basic question. If you are hosting a WCF service in a Windows Service where are the webpages hosted if you want remote machines to access the WCF service? Remote access rules out using the visual studio development web server. Can you use IIS to still provide remote access without having IIS host the WCF service? If you can use IIS to host the webpages, how do you go about publishing the WCF service?

    Thanks,
    dst

  45. Dennis van der Stelt says:

    A lot of questions… πŸ™‚

    Where are webpages hosted? Regular webpages are always hosted in IIS and WCF can’t help with that. The webpages that need to access WCF can use any protocol supported by WCF to access the WCF service. Remote machines can do exactly the same.

    Visual Studio dev webserver isn’t a real webserver, it’s only there for local debugging purposes. You should really use IIS to host websites.

    I’m not sure why you keep talking about webpages and WCF service. These are completely different things!!!

    The webpages are hosted on IIS, the WCF service can be anywhere else. Remote machines can access both of them, but both will have different addresses.

    I have the feeling you’re not telling me what it is you’re trying to solve. You’ve only provided me the problem you have. What are you trying to accomplish?

    Do you need a website that shows data to end-users and a WCF service that provides the same data to other applications? That should be no problem at all.

    Also, why are you unable to host WCF in IIS? This is a better solution in almost any situation!!!

  46. Venkat Prasad M S says:

    Am not sure where to start. I have written a WCF Duplex Windows service. I was getting an error, port 80xx is used by another application, ss I hadn’t set the clientbaseaddress, it got corrected.

    I installed it as a windows service, and my client program was able to communicate with the service and messages got published. This was in the development environment, and hence wanted to change a few things in the component. I changed code, uninstalled the service, and installed the service. I started getting the error from where I started this, but this time am using clientbaseaddress in the config file for sure.

    Where am I going wrong?

  47. kurt says:

    Dennis, is the source code still available for download?

    The current link (http://dennis.bloggingabout.net/files/MSMQ-Example.zip) returns a 404 error.

  48. Yaron says:

    Still no news on the dead link ? πŸ™
    Trying to find a mirror, but still no luck ..

  49. I’m sorry for the wait, the link should now work again!

  50. Mathieu Beliveau says:

    Hi Dennis! Thanks for the post. For a moment, I thought this could be the solution to my problem. Namely, I spent all day trying to understand why my application, when running as a Windows Service will not process the messages in it’s designated queue (while everything is fine when the application is running as a normal app). I have glanced over your code sample and it seems very similar to what I’ve done. At this point, I’m pretty much clueless about what could be the cause of my issue.

    Here are some details: http://stackoverflow.com/questions/25554510/msmq-application-does-not-process-queued-messages-when-running-as-windows-servic

    This is happenning on a Windows 7 machine as well as on a Windows 2012r2 server.

    If you could at the very least provide some general direction or hints on how I could even begin to know what fails, it would greatly be appreciated!

    Thanks!

Click on a tab to select how you'd like to leave your comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.