Delen via


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 CalculatorServiceis 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 OnStartwordt 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

  1. Maak een nieuw Visual Studio Console-app-project met de naam Service.

  2. Wijzig de naam van Program.cs in Service.cs.

  3. Wijzig de naamruimte in Microsoft.ServiceModel.Samples.

  4. Voeg verwijzingen toe aan de volgende assembly's:

    • System.ServiceModel.dll
    • System.ServiceProcess.dll
    • System.Configuration.Install.dll
  5. 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
    
  6. 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
    
  7. 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
    
  8. Maak een nieuwe klasse die wordt overgenomen CalculatorWindowsService van de ServiceBase klasse. Voeg een lokale variabele toe die wordt aangeroepen serviceHost om te verwijzen naar het ServiceHost exemplaar. De methode definiëren die aanroept MainServiceBase.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
    
  9. 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
    
  10. 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
    
  11. Maak een nieuwe klasse ProjectInstaller die wordt overgenomen van Installer en die is gemarkeerd met de RunInstallerAttribute set op true. 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
    
  12. Verwijder de Service klasse die is gegenereerd toen u het project maakte.

  13. 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 trueop, 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

  1. Bouw de oplossing om het Service.exe uitvoerbare bestand te maken.

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

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

Zie ook