Bagikan melalui


Cara: Meng-hosting Layanan WCF di Layanan Windows Terkelola

Topik ini menguraikan langkah-langkah dasar yang diperlukan untuk membuat layanan Windows Communication Foundation (WCF) yang dihosting di Layanan Windows. Skenario ini diaktifkan oleh opsi hosting layanan Windows terkelola yang merupakan layanan WCF yang berjalan lama yang dihosting di luar IIS di lingkungan aman yang tidak diaktifkan pesan. Masa pakai layanan dikendalikan sebagai gantinya oleh sistem operasi. Opsi hosting ini tersedia di semua versi Windows.

Layanan Windows dapat dikelola dengan Microsoft.ManagementConsole.SnapIn di Microsoft Management Console (MMC) dan dapat dikonfigurasi untuk memulai secara otomatis saat sistem di-boot. Opsi hosting ini terdiri dari mendaftarkan domain aplikasi (AppDomain) yang menghosting layanan WCF sebagai Layanan Windows terkelola sehingga masa pakai proses layanan dikendalikan oleh Manajer Kontrol Layanan (SCM) untuk layanan Windows.

Kode layanan mencakup implementasi layanan kontrak layanan, kelas Layanan Windows, dan kelas alat penginstal. Kelas implementasi layanan, CalculatorService, adalah layanan WCF. CalculatorWindowsService adalah layanan Windows. Untuk memenuhi syarat sebagai layanan Windows, kelas mewarisi dari ServiceBase dan menerapkan metode OnStart dan OnStop. Di OnStart, ServiceHost dibuat untuk jenis CalculatorService dan dibuka. Dalam OnStop, layanan dihentikan dan dibuang. Host juga bertanggung jawab untuk memberikan alamat dasar ke host layanan, yang telah dikonfigurasi dalam pengaturan aplikasi. Kelas alat penginstal, yang mewarisi dari Installer, memungkinkan program diinstal sebagai layanan Windows oleh alat Installutil.exe.

Buat layanan dan berikan kode hosting

  1. Buat proyek aplikasi Console Visual Studio baru yang disebut Layanan.

  2. Ganti nama Program.cs menjadi Service.cs.

  3. Ubah namespace layanan menjadi Microsoft.ServiceModel.Samples.

  4. Tambahkan referensi ke rakitan berikut:

    • System.ServiceModel.dll
    • System.ServiceProcess.dll
    • System.Configuration.Install.dll
  5. Tambahkan arahan berikut using ke 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. Tentukan kontrak layanan ICalculator seperti yang ditunjukkan dalam kode berikut.

    // 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. Terapkan kontrak layanan di kelas yang disebut CalculatorService seperti yang ditunjukkan dalam kode berikut.

    // 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. Buat kelas baru yang disebut CalculatorWindowsService yang mewarisi dari kelas ServiceBase. Tambahkan variabel lokal yang disebut serviceHost untuk mereferensikan instans ServiceHost. Tentukan metode Main yang memanggil 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
    
  9. Ambil alih metode OnStart(String[]) dengan membuat dan membuka instans ServiceHost baru seperti yang ditunjukkan dalam kode berikut.

    // 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. Ambil alih metode OnStop, tutup ServiceHost seperti yang ditunjukkan dalam kode berikut.

    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. Buat kelas baru yang disebut ProjectInstaller yang mewarisi dari Installer dan yang ditandai dengan RunInstallerAttribute yang diatur ke true. Ini memungkinkan layanan Windows diinstal oleh alat 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. Hapus kelas Service yang dihasilkan saat Anda membuat proyek.

  13. Tambahkan file konfigurasi aplikasi ke proyek. Ganti isi file dengan konfigurasi XML berikut.

    <?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 kanan file App.config di Penjelajah Solusi dan pilih Properti. Di Salin ke Direktori Output, pilih Salin jika Lebih Baru.

    Contoh ini secara eksplisit menentukan titik akhir dalam file konfigurasi. Jika Anda tidak menambahkan titik akhir apa pun ke layanan, runtime bahasa umum menambahkan titik akhir default untuk Anda. Dalam contoh ini, karena layanan memiliki ServiceMetadataBehavior yang diatur ke true, layanan Anda juga mengaktifkan metadata penerbitan. Untuk informasi selengkapnya tentang titik akhir, pengikatan, dan perilaku default, lihat Konfigurasi Sederhana dan Konfigurasi Sederhana untuk Layanan WCF.

Menginstal dan menjalankan layanan

  1. Buat solusi untuk membuat Service.exe dapat dieksekusi.

  2. Buka Perintah Pengembang untuk Visual Studio dan navigasikan ke direktori proyek. Ketik installutil bin\service.exe pada perintah untuk menginstal layanan Windows.

    Ketik services.msc pada perintah untuk mengakses Service Control Manager (SCM). Layanan Windows akan muncul di Layanan sebagai "WCFWindowsServiceSample". Layanan WCF hanya dapat menanggapi klien jika Layanan Windows berjalan. Untuk memulai layanan, klik kanan di SCM dan pilih "Start", atau ketik net start WCFWindowsServiceSample di perintah.

  3. Jika Anda membuat perubahan pada layanan, Anda harus terlebih dahulu menghentikannya dan menghapus instalan. Untuk menghentikan layanan, klik kanan layanan di SCM dan pilih "Stop", atau ketik net stop WCFWindowsServiceSample di perintah. Perhatikan bahwa jika Anda menghentikan layanan Windows lalu menjalankan klien, pengecualian EndpointNotFoundException terjadi ketika klien mencoba mengakses layanan. Untuk menghapus instalan layanan Windows ketik installutil /u bin\service.exe pada perintah.

Contoh

Berikut ini adalah daftar lengkap kode yang digunakan dalam topik ini:

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

Seperti opsi “Hosting Mandiri”, lingkungan hosting layanan Windows ini mengharuskan beberapa kode hosting ditulis sebagai bagian dari aplikasi. Layanan ini diimplementasikan sebagai aplikasi konsol dan berisi kode hostingnya sendiri. Di lingkungan hosting lain, seperti Windows Process Activation Services (WAS) atau Layanan Informasi Internet (IIS), Pengembang tidak perlu menulis kode hosting.

Lihat juga