Dennis van der Stelt

The most votes generally drown out the best votes

Community

News

  • Addicted to Refactor! Pro

Email Notifications

I read...

I Use...

Tags

Recent Posts

Archives

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.

    1 ServiceHost _host = null;

    2 

    3 protected override void OnStart(string[] args)

    4 {

    5   string queueName = ConfigurationManager.AppSettings["SendMailQueueName"];

    6 

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

    8 

    9   if (!MessageQueue.Exists(queueName))

   10   {

   11     Trace.WriteLine("Creating queue : " + queueName);

   12     MessageQueue.Create(queueName, true);

   13   }

   14 

   15   _host = new ServiceHost(typeof(SendMailService));

   16   _host.Open();

   17 }

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.

Comments

Mike said:

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

# April 5, 2008 5:23 PM

Dennis van der Stelt said:

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

# April 7, 2008 10:22 AM

Morgan said:

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

# May 8, 2008 11:49 AM

HANK said:

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

# October 9, 2008 9:32 PM

Akhil Jadhav said:

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.

# December 31, 2008 7:28 AM

charlie said:

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.

# February 2, 2009 12:22 PM

Dennis van der Stelt said:

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.

# February 2, 2009 1:18 PM

kakalot said:

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

# April 24, 2009 6:44 AM

Dennis van der Stelt said:

@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.

# April 24, 2009 1:14 PM

kakalot said:

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.

# May 12, 2009 12:31 PM

casino gambling forum said:

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?

# June 24, 2009 9:14 AM

Dennis van der Stelt said:

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! :)

# June 24, 2009 10:21 AM

Twonne said:

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: msdn.microsoft.com/.../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?

# July 28, 2009 9:27 AM

Alex said:

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 ?

# August 13, 2009 7:25 AM

Rose said:

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~

# December 9, 2009 7:33 PM

Dennis van der Stelt said:

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:

bloggingabout.net/.../WCF-Part-6-_3A00_-Address.aspx

# December 9, 2009 10:15 PM

Kiran said:

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?

# December 24, 2009 6:20 AM

Dennis van der Stelt said:

@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.

# December 24, 2009 7:38 AM

Sowmya said:

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

# February 3, 2010 12:32 PM

Dennis van der Stelt said:

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

# February 3, 2010 2:58 PM

Sowmya said:

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

# February 6, 2010 6:32 AM

Mukund said:

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?

# March 2, 2010 8:00 PM

Dennis van der Stelt said:

@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.

# March 3, 2010 11:26 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Please add 3 and 4 and type the answer here: