WCF 服務必須在「宿主」中執行。常見裝載方式有四種:IIS / WAS (Windows Process Activation Service) / Windows Service / 自我裝載 (Self-Host / Console/WinForm/WPF)。各有優劣,選型需依部署環境、啟動需求、管理便利性決定。本篇以 Windows Service 裝載 為主軸,完整示範從服務安裝、啟動、WCF 整合到用戶端呼叫的端到端流程。
| 裝載方式 | 啟動模式 | 進程管理 | 適用場景 | 缺點 |
|---|---|---|---|---|
| IIS / WAS | 訊息觸發啟動 (按需) | IIS/WAS 自動管理回收、健康監控 | Web 應用、HTTP/HTTPS 服務、需高可用性 | 僅支援 HTTP/Net.Tcp (WAS);部署相對複雜 |
| Windows Service | 開機自動/手動啟動 | SCM (Service Control Manager) 管理 | 長期運行、非 HTTP 協定 (TCP, Named Pipe)、需開機即服務 | 需管理員權限安裝;手動更新較麻煩 |
| 自我裝載 | 應用程式啟動時手動 Open() | 開發者自行控制 | 開發測試、桌面應用內嵌服務、簡單部署 | 無自動回收、健康監控;生產環境較少用 |
// IHello.cs
using System.ServiceModel;
namespace WCF.ServiceLib.Sample
{
[ServiceContract]
public interface IHello
{
[OperationContract]
string SayHello(string name);
}
}
// Hello.cs
namespace WCF.ServiceLib.Sample
{
public class Hello : IHello
{
public string SayHello(string name) => $"Hello: {name}";
}
}
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace WCF.ServiceHostByWindowsService.Sample
{
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
public ProjectInstaller()
{
var process = new ServiceProcessInstaller { Account = ServiceAccount.LocalSystem };
var service = new ServiceInstaller
{
ServiceName = "WCF.ServiceHostByWindowsService",
DisplayName = "WCF 服務宿主範例",
Description = "示範 WCF 服務裝載於 Windows Service",
StartType = ServiceStartMode.Automatic
};
Installers.AddRange(new Installer[] { process, service });
}
}
}
using System;
using System.ServiceModel;
using System.ServiceProcess;
using WCF.ServiceLib.Sample;
namespace WCF.ServiceHostByWindowsService.Sample
{
public class WindowsService : ServiceBase
{
private ServiceHost _host;
public static void Main() => ServiceBase.Run(new WindowsService());
public WindowsService() => ServiceName = "WCF.ServiceHostByWindowsService";
protected override void OnStart(string[] args)
{
_host?.Close();
_host = new ServiceHost(typeof(Hello));
_host.Open(); // 依 App.config 開啟端點
// 可選:訂閱 ServiceHost 事件進行監控
_host.Faulted += (s, e) =>
{
// 記錄錯誤、嘗試重啟等
System.Diagnostics.EventLog.WriteEntry("WCFHost", "ServiceHost 進入 Faulted 狀態", System.Diagnostics.EventLogEntryType.Error);
};
}
protected override void OnStop()
{
_host?.Close();
_host = null;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<services>
<service name="WCF.ServiceLib.Sample.Hello" behaviorConfiguration="SampleBehavior">
<endpoint address=""
binding="wsHttpBinding"
contract="WCF.ServiceLib.Sample.IHello" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:11233/ServiceHostByWindowsService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SampleBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
InstallUtil.exe WCF.ServiceHostByWindowsService.exehttps://localhost:11233/ServiceHostByWindowsService/ 驗證 WSDL 是否正常// Hello.aspx.cs
public partial class Hosting_Hello : System.Web.UI.Page
{
protected void btnSayHello_Click(object sender, EventArgs e)
{
var proxy = new HostingByWindowsService.HelloClient();
var result = proxy.SayHello(txtName.Text);
ClientScript.RegisterStartupScript(GetType(), "msg", $"alert('{result}');", true);
proxy.Close();
}
}
<client>
<endpoint address="https://localhost:11233/ServiceHostByWindowsService/"
binding="wsHttpBinding"
contract="Sample.IHello" />
</client>
在 `ProjectInstaller` 中或透過 `sc.exe` 設定失敗自動重啟:
sc failure "WCF.ServiceHostByWindowsService" reset= 86400 actions= restart/60000/restart/120000/restart/180000
if (!EventLog.SourceExists("WCFHost"))
EventLog.CreateEventSource("WCFHost", "Application");
在同一 `ServiceHost` 新增多個 Endpoint:
_host.AddServiceEndpoint(typeof(IHello), new NetTcpBinding(), "net.tcp://localhost:54321/Hello");
_host.AddServiceEndpoint(typeof(IHello), new NetNamedPipeBinding(), "net.pipe://localhost/Hello");