How to: Host a WCF Service in a Managed Windows Service
This topic outlines the basic steps required to create a Windows Communication Foundation (WCF) service that is hosted by a Windows Service. The scenario is enabled by the managed Windows service hosting option that is a long-running WCF service hosted outside of Internet Information Services (IIS) in a secure environment that is not message activated. The lifetime of the service is controlled instead by the operating system. This hosting option is available in all versions of Windows.
Windows services can be managed with the Microsoft.ManagementConsole.SnapIn in Microsoft Management Console (MMC) and can be configured to start up automatically when the system boots up. This hosting option consists of registering the application domain (AppDomain) that hosts a WCF service as a managed Windows service so that the process lifetime of the service is controlled by the Service Control Manager (SCM) for Windows services.
The service code includes a service implementation of the service contract, a Windows Service class, and an installer class. The service implementation class, CalculatorService, is a WCF service. The CalculatorWindowsService is a Windows service. To qualify as a Windows service, the class inherits from ServiceBase and implements the OnStart and OnStop methods. In OnStart, a ServiceHost is created for the CalculatorService type and opened. In OnStop, the service is stopped and disposed. The host is also responsible for providing a base address to the service host, which has been configured in application settings. The installer class, which inherits from Installer, allows the program to be installed as a Windows service by the Installutil.exe tool.
Construct the service and provide the hosting code
-
Create a new Visual Studio Console Application project called "Service".
-
Rename Program.cs to Service.cs.
-
Change the namespace to Microsoft.ServiceModel.Samples.
-
Add references to the following assemblies.
-
System.ServiceModel.dll
-
System.ServiceProcess.dll
-
System.Configuration.Install.dll
-
System.ServiceModel.dll
-
Add the following using statements to Service.cs.
-
Define the
ICalculatorservice contract as shown in the following code.// Define a service contract. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); }
-
Implement the service contract in a class called
CalculatorServiceas shown in the following code.// Implement the ICalculator service contract in a service class. public class CalculatorService : ICalculator { // Implement the ICalculator methods. public double Add(double n1, double n2) { double result = n1 + n2; return result; } public double Subtract(double n1, double n2) { double result = n1 - n2; return result; } public double Multiply(double n1, double n2) { double result = n1 * n2; return result; } public double Divide(double n1, double n2) { double result = n1 / n2; return result; } }
-
Create a new class called
CalculatorWindowsServicethat inherits from the ServiceBase class. Add a local variable calledserviceHostto reference the ServiceHost instance. Define theMainmethod that callsServiceBase.Run(new CalculatorWindowsService) -
Override the OnStart method by creating and opening a new ServiceHost instance as shown in the following code.
// Start the Windows service. protected override void OnStart(string[] args) { if (serviceHost != null) { serviceHost.Close(); } // Create a ServiceHost for the CalculatorService type and // provide the base address. serviceHost = new ServiceHost(typeof(CalculatorService)); // Open the ServiceHostBase to create listeners and start // listening for messages. serviceHost.Open(); }
-
Override the OnStop method closing the ServiceHost as shown in the following code.
-
Create a new class called
ProjectInstallerthat inherits from Installer and that is marked with the RunInstallerAttribute set to true. This allows the Windows service to be installed by the Installutil.exe tool.// Provide the ProjectInstaller class which allows // the service to be installed by the Installutil.exe tool [RunInstaller(true)] public class ProjectInstaller : Installer { private ServiceProcessInstaller process; private ServiceInstaller service; public ProjectInstaller() { process = new ServiceProcessInstaller(); process.Account = ServiceAccount.LocalSystem; service = new ServiceInstaller(); service.ServiceName = "WCFWindowsServiceSample"; Installers.Add(process); Installers.Add(service); } }
-
Remove the
Serviceclass that was generated when you created the project. -
Add an application configuration file to the project. Replace the contents of the file with the following configuration XML.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <!-- This section is optional with the new configuration model introduced in .NET Framework 4. --> <service name="Microsoft.ServiceModel.Samples.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/> </baseAddresses> </host> <!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModelSamples/service --> <endpoint address="" binding="wsHttpBinding" contract="Microsoft.ServiceModel.Samples.ICalculator" /> <!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="CalculatorServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
Right click the App.config file in the Solution Explorer and select Properties. Under Copy to Output Directory select Copy if Newer.
This example explicitly specifies endpoints in the configuration file. If you do not add any endpoints to the service, the runtime adds default endpoints for you. In this example, because the service has a ServiceMetadataBehavior set to true, your service also has publishing metadata enabled. For more information aboutdefault endpoints, bindings, and behaviors, see Simplified Configuration and Simplified Configuration for WCF Services.
Install and run the service
-
Build the solution to create the
Service.exeexecutable. -
Open the Visual Studio 2010 command prompt and navigate to the project directory. Type
installutil bin\service.exeat the command prompt to install the Windows service.
Note: If you do not use the Visual Studio 2010 command prompt, make sure that the %WinDir%\Microsoft.NET\Framework\v4.0.<current version>directory is in the system path.Type
services.mscat the command prompt to access the Service Control Manager (SCM). The Windows service should appear in Services as "WCFWindowsServiceSample". The WCF service can only respond to clients if the Windows service is running. To start the service, right-click it in the SCM and select "Start", or type net start WCFWindowsServiceSample at the command prompt. -
If you make changes to the service, you must first stop it and uninstall it. To stop the service, right-click the service in the SCM and select "Stop", or type net stop WCFWindowsServiceSample at the command prompt. Note that if you stop the Windows service and then run a client, an EndpointNotFoundException exception occurs when a client attempts to access the service. To uninstall the Windows service type installutil /u bin\service.exe at the command prompt.
Example
The following is a complete listing of the code used by this topic.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ServiceModel; using System.ServiceProcess; using System.Configuration; using System.Configuration.Install; namespace Microsoft.ServiceModel.Samples { // Define a service contract. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); } // Implement the ICalculator service contract in a service class. public class CalculatorService : ICalculator { // Implement the ICalculator methods. public double Add(double n1, double n2) { double result = n1 + n2; return result; } public double Subtract(double n1, double n2) { double result = n1 - n2; return result; } public double Multiply(double n1, double n2) { double result = n1 * n2; return result; } public double Divide(double n1, double n2) { double result = n1 / n2; return result; } } public class CalculatorWindowsService : ServiceBase { public ServiceHost serviceHost = null; public CalculatorWindowsService() { // Name the Windows Service ServiceName = "WCFWindowsServiceSample"; } public static void Main() { ServiceBase.Run(new CalculatorWindowsService()); } // Start the Windows service. protected override void OnStart(string[] args) { if (serviceHost != null) { serviceHost.Close(); } // Create a ServiceHost for the CalculatorService type and // provide the base address. serviceHost = new ServiceHost(typeof(CalculatorService)); // Open the ServiceHostBase to create listeners and start // listening for messages. serviceHost.Open(); } protected override void OnStop() { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } } } // Provide the ProjectInstaller class which allows // the service to be installed by the Installutil.exe tool [RunInstaller(true)] public class ProjectInstaller : Installer { private ServiceProcessInstaller process; private ServiceInstaller service; public ProjectInstaller() { process = new ServiceProcessInstaller(); process.Account = ServiceAccount.LocalSystem; service = new ServiceInstaller(); service.ServiceName = "WCFWindowsServiceSample"; Installers.Add(process); Installers.Add(service); } } }
Like the "Self-Hosting" option, the Windows service hosting environment requires that some hosting code be written as part of the application. The service is implemented as a console application and contains its own hosting code. In other hosting environments, such as Windows Process Activation Service (WAS) hosting in Internet Information Services (IIS), it is not necessary for developers to write hosting code.
See Also
Remove the Service class that was generated when you created the project.
I understood, that all the code should go to Service class. If I delete it, what will remain?
- 2/14/2012
- pappasa
- 1/9/2012
- tamer yousef
- 1/9/2012
- tamer yousef
Also please note that you might need to add a Pre-Build command in to the project as Copy $(ProjectDir)App.config $(TargetDir)$(TargetFileName).config This will copy the App.Config to ProjectFileName.exe.config to the output folder.
*** YOU ARE A LEGEND DUDE THANKYOU VERY MUCH EVERYTHING WORKS PERFECTLY *** - Josh
- 12/25/2010
- Jebarson J
- 12/5/2011
- Josh Ash
- 12/1/2011
- MichFuchs
- After following the instructions, I was able to get this how to work. There were just a few bits that I needed to add.
- Run the Visual Studio 2010 Command Prompt as an administrator.
- Do this by right clicking on the VS 2010 Command Prompt and then choosing Run as Administrator.
- Run installutil bin\debug\service.exe instead of bin\service.exe because my service.exe went into the bin\debug folder.
- By making these changes, the how to worked for me with .NET 4.0
- 11/20/2011
- ShaunLuttin
- 7/2/2011
- Priyank Thakkar
- 6/8/2011
- robertstackhouse
- 5/13/2011
- Yakeir
- 5/4/2011
- vikas02
FINDING: Step #3 of the instructions state: "Change the namespace to Microsoft.ServiceModel.Samples." So, in the C# project I went into the project properties and edited the namespace field to be Microsoft.ServiceModel.Samples. Everything worked fine. When I did the same on the VB project I actually got an error that it couldn't find the default main() function to run and made me pick it from a list. Strangely, the only option started out with "Microsoft.ServiceModel.Samples.Microsoft.ServiceModel.Samples....". Which made start thinking something was screwy with the VB namespace. COME TO FIND OUT, the namespace field for the C# project was actually titled "Default Namespace" while the VB field was titled "Root Namespace". While I thought I was doing the same thing in each step, I was actually setting two slightly different properties that sat in the same place on the properties page. Why is C#/VB different like this???
FIX: For the VB project, set the Root Namespace field to nothing, for the C# project, set the Default Namespace field to "Microsoft.ServiceModel.Samples".
- 4/4/2011
- dascth
guide from a given template (isnt that what they are there for). Plus, having
two separate projects (i.e. one for Win
Service and one for WCF Service) should be the way to create this solution, not
have them merged in to one. I’ve been unsuccessful at creating a solution with
two projects, if some knows how, please let the rest of us know. Tnx
- 3/29/2011
- Me to
wcfwindowsservicesample service on local computer started and stopped. some service stop automatically if they are not in use by other service or programs.
the service runs in system account.
- 2/23/2011
- Senthil Nachimuthu
wcfwindowsservicesample service on local computer started and stopped. some service stop automatically if they are not in use by other service or programs.
the service runs in system account.
- 2/23/2011
- Senthil Nachimuthu
For those who say "it's all the same," no, it is NOT all the same. The Windows Service template uses a partial class for the ServiceBase and separates the Main() method into a Program class, neither of which are germane to this how-to.
Also, in the real world, nobody is going to build a single project that encompasses all functionality. Some reasonable expectations for how to build this as a solution, not a single project, are not out of bounds.
- 12/14/2010
- PJBlecha
http://richardwilburn.wordpress.com/2010/12/01/wcf-windows-service-deployment/
- 12/1/2010
- Dessus
You can find the blog post that includes a reference to the source code here:
http://peterkellner.net/2010/06/18/wcf-service-in-managed-windows-service-vs2010-2/
Hope this helps!
- 6/18/2010
- pkellner
You can find the blog post that includes a reference to the source code here:
http://peterkellner.net/2010/06/18/wcf-service-in-managed-windows-service-vs2010-2/
- 6/18/2010
- pkellner