Procedure: Een WCF-service hosten in een beheerde Windows-service
In dit onderwerp vindt u een overzicht van de basisstappen die nodig zijn om een WCF-service (Windows Communication Foundation) te maken die wordt gehost door een Windows-service. Het scenario wordt ingeschakeld door de beheerde windows-servicehostingoptie die een langlopende WCF-service is die wordt gehost buiten Internet Information Services (IIS) in een beveiligde omgeving die niet wordt geactiveerd. De levensduur van de service wordt in plaats daarvan beheerd door het besturingssysteem. Deze hostingoptie is beschikbaar in alle versies van Windows.
Windows-services kunnen worden beheerd met de Microsoft.ManagementConsole.SnapIn in Microsoft Management Console (MMC) en kunnen worden geconfigureerd om automatisch te worden opgestart wanneer het systeem wordt opgestart. Deze hostingoptie bestaat uit het registreren van het toepassingsdomein (AppDomain) dat als host fungeert voor een WCF-service als een beheerde Windows-service, zodat de proceslevensduur van de service wordt beheerd door de Service Control Manager (SCM) voor Windows-services.
De servicecode bevat een service-implementatie van het servicecontract, een Windows-serviceklasse en een installatieklasse. De service-implementatieklasse CalculatorService
is een WCF-service. Het CalculatorWindowsService
is een Windows-service. Als u wilt kwalificeren als een Windows-service, neemt de klasse de en methoden over ServiceBase
en implementeert dezeOnStart
.OnStop
Er OnStart
wordt een ServiceHost gemaakt voor het CalculatorService
type en geopend. In OnStop
, de service wordt gestopt en verwijderd. De host is ook verantwoordelijk voor het verstrekken van een basisadres aan de servicehost, die is geconfigureerd in toepassingsinstellingen. Met de installatieklasse, waarvan het programma wordt Installerovergenomen, kan het programma worden geïnstalleerd als een Windows-service door het hulpprogramma Installutil.exe.
Bouw de service en geef de hostingcode op
Maak een nieuw Visual Studio Console-app-project met de naam Service.
Wijzig de naam van Program.cs in Service.cs.
Wijzig de naamruimte in
Microsoft.ServiceModel.Samples
.Voeg verwijzingen toe aan de volgende assembly's:
- System.ServiceModel.dll
- System.ServiceProcess.dll
- System.Configuration.Install.dll
Voeg de volgende
using
instructies toe aan Service.cs.using System.ComponentModel; using System.ServiceModel; using System.ServiceProcess; using System.Configuration; using System.Configuration.Install;
Imports System.ComponentModel Imports System.ServiceModel Imports System.ServiceProcess Imports System.Configuration Imports System.Configuration.Install
Definieer het
ICalculator
servicecontract, zoals wordt weergegeven in de volgende 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); }
' Define a service contract. <ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _ Public Interface ICalculator <OperationContract()> _ Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double <OperationContract()> _ Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double <OperationContract()> _ Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double <OperationContract()> _ Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double End Interface
Implementeer het servicecontract in een klasse die wordt aangeroepen
CalculatorService
, zoals wordt weergegeven in de volgende 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; } }
' Implement the ICalculator service contract in a service class. Public Class CalculatorService Implements ICalculator ' Implement the ICalculator methods. Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add Return n1 + n2 End Function Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract Return n1 - n2 End Function Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply Return n1 * n2 End Function Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide Return n1 / n2 End Function End Class
Maak een nieuwe klasse die wordt overgenomen
CalculatorWindowsService
van de ServiceBase klasse. Voeg een lokale variabele toe die wordt aangeroepenserviceHost
om te verwijzen naar het ServiceHost exemplaar. De methode definiëren die aanroeptMain
ServiceBase.Run(new CalculatorWindowsService)
public class CalculatorWindowsService : ServiceBase { public ServiceHost serviceHost = null; public CalculatorWindowsService() { // Name the Windows Service ServiceName = "WCFWindowsServiceSample"; } public static void Main() { ServiceBase.Run(new CalculatorWindowsService()); }
Public Class CalculatorWindowsService Inherits ServiceBase Public serviceHost As ServiceHost = Nothing Public Sub New() ' Name the Windows Service ServiceName = "WCFWindowsServiceSample" End Sub Public Shared Sub Main() ServiceBase.Run(New CalculatorWindowsService()) End Sub
Overschrijf de OnStart(String[]) methode door een nieuw ServiceHost exemplaar te maken en te openen, zoals wordt weergegeven in de volgende 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(); }
' Start the Windows service. Protected Overrides Sub OnStart(ByVal args() As String) If serviceHost IsNot Nothing Then serviceHost.Close() End If ' Create a ServiceHost for the CalculatorService type and ' provide the base address. serviceHost = New ServiceHost(GetType(CalculatorService)) ' Open the ServiceHostBase to create listeners and start ' listening for messages. serviceHost.Open() End Sub
Overschrijf de methode om de OnStop ServiceHost methode te sluiten, zoals wordt weergegeven in de volgende code.
protected override void OnStop() { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } }
Protected Overrides Sub OnStop() If serviceHost IsNot Nothing Then serviceHost.Close() serviceHost = Nothing End If End Sub
Maak een nieuwe klasse
ProjectInstaller
die wordt overgenomen van Installer en die is gemarkeerd met de RunInstallerAttribute set optrue
. Hierdoor kan de Windows-service worden geïnstalleerd door het hulpprogramma Installutil.exe.// 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); } }
' Provide the ProjectInstaller class which allows ' the service to be installed by the Installutil.exe tool <RunInstaller(True)> _ Public Class ProjectInstaller Inherits Installer Private process As ServiceProcessInstaller Private service As ServiceInstaller Public Sub New() process = New ServiceProcessInstaller() process.Account = ServiceAccount.LocalSystem service = New ServiceInstaller() service.ServiceName = "WCFWindowsServiceSample" Installers.Add(process) Installers.Add(service) End Sub End Class
Verwijder de
Service
klasse die is gegenereerd toen u het project maakte.Voeg een toepassingsconfiguratiebestand toe aan het project. Vervang de inhoud van het bestand door de volgende configuratie-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>
Klik met de rechtermuisknop op het bestand App.config in Solution Explorer en selecteer Eigenschappen. Selecteer Onder Kopiëren naar uitvoermap de optie Kopiëren als nieuwer.
In dit voorbeeld worden expliciet eindpunten in het configuratiebestand opgegeven. Als u geen eindpunten aan de service toevoegt, voegt de runtime standaardeindpunten voor u toe. Omdat de service in dit voorbeeld is ServiceMetadataBehavior ingesteld
true
op, is voor uw service ook publicatiemetagegevens ingeschakeld. Zie Vereenvoudigde configuratie en vereenvoudigde configuratie voor WCF-services voor meer informatie over standaardeindpunten, bindingen en gedrag.
De service installeren en uitvoeren
Bouw de oplossing om het
Service.exe
uitvoerbare bestand te maken.Open de opdrachtprompt voor Ontwikkelaars voor Visual Studio en navigeer naar de projectmap. Typ
installutil bin\service.exe
bij de opdrachtprompt om de Windows-service te installeren.Typ
services.msc
bij de opdrachtprompt om toegang te krijgen tot Service Control Manager (SCM). De Windows-service moet worden weergegeven in Services als WCFWindowsServiceSample. De WCF-service kan alleen reageren op clients als de Windows-service wordt uitgevoerd. Als u de service wilt starten, klikt u er met de rechtermuisknop op in de SCM en selecteert u 'Start' of typt u net start WCFWindowsServiceSample bij de opdrachtprompt.Als u wijzigingen aanbrengt in de service, moet u deze eerst stoppen en verwijderen. Als u de service wilt stoppen, klikt u met de rechtermuisknop op de service in de SCM en selecteert u 'Stoppen' of typt u netstop WCFWindowsServiceSample bij de opdrachtprompt. Als u de Windows-service stopt en vervolgens een client uitvoert, treedt er een EndpointNotFoundException uitzondering op wanneer een client probeert toegang te krijgen tot de service. Als u het Windows-servicetype installutil /u bin\service.exe wilt verwijderen via de opdrachtprompt.
Opmerking
Hier volgt een volledig overzicht van de code die in dit onderwerp wordt gebruikt:
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);
}
}
}
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.ComponentModel
Imports System.ServiceModel
Imports System.ServiceProcess
Imports System.Configuration
Imports System.Configuration.Install
Namespace Microsoft.ServiceModel.Samples
' Define a service contract.
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
<OperationContract()> _
Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
End Interface
' Implement the ICalculator service contract in a service class.
Public Class CalculatorService
Implements ICalculator
' Implement the ICalculator methods.
Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
Return n1 + n2
End Function
Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
Return n1 - n2
End Function
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
Return n1 * n2
End Function
Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
Return n1 / n2
End Function
End Class
Public Class CalculatorWindowsService
Inherits ServiceBase
Public serviceHost As ServiceHost = Nothing
Public Sub New()
' Name the Windows Service
ServiceName = "WCFWindowsServiceSample"
End Sub
Public Shared Sub Main()
ServiceBase.Run(New CalculatorWindowsService())
End Sub
' Start the Windows service.
Protected Overrides Sub OnStart(ByVal args() As String)
If serviceHost IsNot Nothing Then
serviceHost.Close()
End If
' Create a ServiceHost for the CalculatorService type and
' provide the base address.
serviceHost = New ServiceHost(GetType(CalculatorService))
' Open the ServiceHostBase to create listeners and start
' listening for messages.
serviceHost.Open()
End Sub
Protected Overrides Sub OnStop()
If serviceHost IsNot Nothing Then
serviceHost.Close()
serviceHost = Nothing
End If
End Sub
End Class
' Provide the ProjectInstaller class which allows
' the service to be installed by the Installutil.exe tool
<RunInstaller(True)> _
Public Class ProjectInstaller
Inherits Installer
Private process As ServiceProcessInstaller
Private service As ServiceInstaller
Public Sub New()
process = New ServiceProcessInstaller()
process.Account = ServiceAccount.LocalSystem
service = New ServiceInstaller()
service.ServiceName = "WCFWindowsServiceSample"
Installers.Add(process)
Installers.Add(service)
End Sub
End Class
End Namespace
Net als de optie 'Self-Hosting' vereist de Windows-servicehostingomgeving dat sommige hostingcode wordt geschreven als onderdeel van de toepassing. De service wordt geïmplementeerd als een consoletoepassing en bevat een eigen hostingcode. In andere hostingomgevingen, zoals het hosten van Windows Process Activation Service (WAS) in IIS (Internet Information Services), is het niet nodig voor ontwikkelaars om hostingcode te schrijven.