Instrukcje: Hostowanie usługi WCF w usłudze zarządzanej systemu Windows
W tym temacie opisano podstawowe kroki wymagane do utworzenia usługi Windows Communication Foundation (WCF), która jest hostowana przez usługę systemu Windows. Scenariusz jest włączony przez zarządzaną opcję hostingu usługi systemu Windows, która jest długotrwałą usługą WCF hostowaną poza usługami Internet Information Services (IIS) w bezpiecznym środowisku, które nie jest aktywowane. Okres istnienia usługi jest kontrolowany przez system operacyjny. Ta opcja hostingu jest dostępna we wszystkich wersjach systemu Windows.
Usługi systemu Windows można zarządzać za pomocą programu Microsoft.ManagementConsole.SnapIn w programie Microsoft Management Console (MMC) i można je skonfigurować do automatycznego uruchamiania po uruchomieniu systemu. Ta opcja hostingu składa się z rejestrowania domeny aplikacji (AppDomain), która hostuje usługę WCF jako zarządzaną usługę systemu Windows, aby okres istnienia procesu usługi był kontrolowany przez menedżera kontroli usług (SCM) dla usług systemu Windows.
Kod usługi zawiera implementację usługi kontraktu usługi, klasę usługi systemu Windows i klasę instalatora. Klasa implementacji usługi, CalculatorService
, jest usługą WCF. Jest CalculatorWindowsService
to usługa systemu Windows. Aby zakwalifikować się jako usługa systemu Windows, klasa dziedziczy i ServiceBase
implementuje OnStart
metody i OnStop
. W OnStart
pliku jest ServiceHost tworzony dla CalculatorService
typu i otwarty. W OnStop
systemie usługa jest zatrzymywana i usuwana. Host jest również odpowiedzialny za podanie podstawowego adresu hosta usługi, który został skonfigurowany w ustawieniach aplikacji. Klasa instalatora, która dziedziczy z Installerprogramu , umożliwia zainstalowanie programu jako usługi systemu Windows przez narzędzie Installutil.exe.
Konstruowanie usługi i dostarczanie kodu hostingu
Utwórz nowy projekt aplikacji konsoli programu Visual Studio o nazwie Usługa.
Zmień nazwę Program.cs na Service.cs.
Zmień przestrzeń nazw na
Microsoft.ServiceModel.Samples
.Dodaj odwołania do następujących zestawów:
- System.ServiceModel.dll
- System.ServiceProcess.dll
- System.Configuration.Install.dll
Dodaj następujące
using
dyrektywy, aby 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
Zdefiniuj
ICalculator
kontrakt usługi, jak pokazano w poniższym kodzie.// 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
Zaimplementuj kontrakt usługi w klasie o nazwie
CalculatorService
, jak pokazano w poniższym kodzie.// 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
Utwórz nową klasę o nazwie
CalculatorWindowsService
, która dziedziczy z ServiceBase klasy . Dodaj zmienną lokalną o nazwieserviceHost
, aby odwołać ServiceHost się do wystąpienia. Definiowanie metody wywołującejMain
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
Zastąpij metodę OnStart(String[]) , tworząc i otwierając nowe ServiceHost wystąpienie, jak pokazano w poniższym kodzie.
// 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
Zastąpi metodę zamykającą ServiceHost metodęOnStop, jak pokazano w poniższym kodzie.
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
Utwórz nową klasę o nazwie
ProjectInstaller
, która dziedziczy z Installer elementu i jest oznaczona zestawem RunInstallerAttribute natrue
wartość . Umożliwia to zainstalowanie usługi systemu Windows przez narzędzie 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
Usuń klasę
Service
wygenerowaną podczas tworzenia projektu.Dodaj plik konfiguracji aplikacji do projektu. Zastąp zawartość pliku następującym kodem XML konfiguracji.
<?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>
Kliknij prawym przyciskiem myszy plik App.config w Eksplorator rozwiązań i wybierz pozycję Właściwości. W obszarze Kopiuj do katalogu wyjściowego wybierz pozycję Kopiuj, jeśli nowsze.
W tym przykładzie jawnie określono punkty końcowe w pliku konfiguracji. Jeśli nie dodasz żadnych punktów końcowych do usługi, środowisko uruchomieniowe doda domyślne punkty końcowe. W tym przykładzie, ponieważ usługa ma ustawioną ServiceMetadataBehavior wartość
true
, usługa ma również włączone metadane publikowania. Aby uzyskać więcej informacji na temat domyślnych punktów końcowych, powiązań i zachowań, zobacz Uproszczone konfigurowanie i uproszczona konfiguracja usług WCF.
Instalowanie i uruchamianie usługi
Skompiluj
Service.exe
rozwiązanie, aby utworzyć plik wykonywalny.Otwórz wiersz polecenia dewelopera dla programu Visual Studio i przejdź do katalogu projektu. Wpisz
installutil bin\service.exe
polecenie w wierszu polecenia, aby zainstalować usługę systemu Windows.Wpisz
services.msc
polecenie w wierszu polecenia, aby uzyskać dostęp do programu Service Control Manager (SCM). Usługa systemu Windows powinna być wyświetlana w obszarze Usługi jako "WCFWindowsServiceSample". Usługa WCF może odpowiadać na klientów tylko wtedy, gdy usługa systemu Windows jest uruchomiona. Aby uruchomić usługę, kliknij ją prawym przyciskiem myszy w SCM i wybierz pozycję "Start" lub wpisz net start WCFWindowsServiceSample w wierszu polecenia.Jeśli wprowadzisz zmiany w usłudze, musisz go najpierw zatrzymać i odinstalować. Aby zatrzymać usługę, kliknij prawym przyciskiem myszy usługę w SCM i wybierz pozycję "Zatrzymaj" lub wpisz polecenie net stop WCFWindowsServiceSample w wierszu polecenia. Należy pamiętać, że jeśli zatrzymasz usługę systemu Windows, a następnie uruchomisz klienta, EndpointNotFoundException wystąpi wyjątek podczas próby uzyskania dostępu do usługi przez klienta. Aby odinstalować typ usługi systemu Windows installutil /u bin\service.exe w wierszu polecenia.
Przykład
Poniżej znajduje się kompletna lista kodu używanego przez ten temat:
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
Podobnie jak opcja "Self-Hosting", środowisko hostingu usług systemu Windows wymaga, aby część kodu hostingu została napisana w ramach aplikacji. Usługa jest implementowana jako aplikacja konsolowa i zawiera własny kod hostingu. W innych środowiskach hostingu, takich jak usługa aktywacji procesów systemu Windows (WAS) hostowanie w usługach Internet Information Services (IIS), nie jest konieczne, aby deweloperzy pisali kod hostingu.