方法: マネージド Windows サービスで WCF サービスをホストする
ここでは、Windows サービスでホストされる Windows Communication Foundation (WCF) サービスを作成するために必要な基本手順について説明します。 このシナリオは、マネージド Windows サービスのホスト オプションによって有効になります。このサービスは、メッセージがアクティブ化されていない、セキュリティ保護された環境において、インターネット インフォメーション サービス (IIS) の外部でホストされ、長時間実行される WCF サービスです。 サービスの有効期限は代わりにオペレーティング システムによって制御されます。 このホスト オプションは Windows のすべてのバージョンで使用できます。
Windows サービスは、Microsoft 管理コンソール (MMC) の Microsoft.ManagementConsole.SnapIn を使用して管理し、システムのブート時に自動的に起動するように構成できます。 このホスト オプションは、WCF サービスをマネージド Windows サービスとしてホストするアプリケーション ドメイン (AppDomain) の登録から構成されているため、サービスのプロセス有効期間は Windows サービスのサービス コントロール マネージャー (SCM) によって制御されます。
サービス コードには、サービス コントラクトのサービス実装、Windows サービス クラス、およびインストーラー クラスが含まれています。 サービス実装クラスである CalculatorService
は WCF サービスです。 一方、CalculatorWindowsService
は Windows サービスです。 Windows サービスとして限定するため、このクラスは ServiceBase
を継承し、OnStart
メソッドと OnStop
メソッドを実装しています。 OnStart
では、ServiceHost 型の CalculatorService
が作成され、開かれます。 OnStop
では、このサービスが停止され、破棄されます。 ホストはベース アドレスをサービス ホストに提供する必要もあります。サービス ホストは、アプリケーション設定で構成されます。 インストーラー クラスは Installer を継承します。このクラスを使用すると、Installutil.exe ツールにより、プログラムを Windows サービスとしてインストールできます。
サービスを構築してホスティング コードを提供する
Service という新しい Visual Studio コンソール アプリ プロジェクトを作成します。
Program.cs を Service.cs に変更します。
名前空間を
Microsoft.ServiceModel.Samples
に変更します。次のアセンブリへの参照を追加します。
- System.ServiceModel.dll
- System.ServiceProcess.dll
- System.Configuration.Install.dll
次の
using
ディレクティブを 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
次のコードに示すように、
ICalculator
サービス コントラクトを定義します。// 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
次のコードに示すように、
CalculatorService
というクラスにサービス コントラクトを実装します。// 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
CalculatorWindowsService
クラスから継承する ServiceBase という新しいクラスを作成します。serviceHost
というローカル変数を追加して、ServiceHost インスタンスを参照します。Main
を呼び出す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
次のコードに示すように、新しい OnStart(String[]) インスタンスを作成して開くことによって ServiceHost メソッドをオーバーライドします。
// 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
次のコードに示すように、OnStop を閉じて ServiceHost メソッドをオーバーライドします。
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
ProjectInstaller
から継承し、Installer に設定された RunInstallerAttribute でマークされたtrue
という新しいクラスを作成します。 これで、Installutil.exe ツールで Windows サービスをインストールできるようになります。// 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
プロジェクトを作成したときに生成された
Service
クラスを削除します。アプリケーション構成ファイルをプロジェクトに追加します。 ファイルの内容を次の構成 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>
ソリューション エクスプローラーで App.config ファイルを右クリックし、 [プロパティ] をクリックします。 [出力ディレクトリにコピー] の下で [新しい場合はコピーする] を選択します。
この例では、構成ファイルにエンドポイントを明示的に指定します。 エンドポイントをサービスに追加しない場合、ランタイムによって既定のエンドポイントが追加されます。 この例では、サービスには ServiceMetadataBehavior に設定された
true
があるので、サービスで公開メタデータも有効化されています。 既定のエンドポイントについては、「Simplified Configuration」 (簡易構成) と「Simplified Configuration for WCF Services」 (WCF サービスの簡易構成) を参照してください。
サービスをインストールして実行する
ソリューションをビルドして
Service.exe
実行可能ファイルを作成します。Visual Studio の開発者コマンド プロンプトを開き、プロジェクト ディレクトリに移動します。 コマンド プロンプトで「
installutil bin\service.exe
」と入力して、Windows サービスをインストールしますコマンド プロンプトで「
services.msc
」と入力してサービス コントロール マネージャー (SCM) にアクセスします。 Windows サービスは、[Services] に "WCFWindowsServiceSample" として表示されます。 この WCF サービスでは、Windows サービスが実行されている場合にのみ、クライアントに応答できます。 サービスを開始するには、SCM でそのサービスを右クリックして [開始] を選択するか、コマンド プロンプトで「net start WCFWindowsServiceSample」と入力します。サービスを変更する場合は、まずそのサービスを停止してからアンインストールする必要があります。 サービスを停止するには、SCM でそのサービスを右クリックして [停止] を選択するか、コマンド プロンプトで「net stop WCFWindowsServiceSample」と入力します。 Windows サービスを停止してクライアントを実行すると、クライアントがこのサービスにアクセスしようとしたときに EndpointNotFoundException 例外が発生することに注意してください。 Windows サービスをアンインストールするには、コマンド プロンプトで「installutil /u bin\service.exe」と入力します。
例
このトピックで使用されているコードの完全な一覧を次に示します。
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
"自己ホスト" オプションと同様、Windows サービス ホスト環境では、ホスト コードをアプリケーションの一部として記述する必要があります。 サービスはコンソール アプリケーションとして実装され、独自のホスティング コードが指定されます。 インターネット インフォメーション サービス (IIS) でホストされる Windows プロセス アクティブ化サービス (WAS) など、他のホスト環境ではホスティング コードを記述する必要はありません。