通过Windows服务托管WCF服务的实现方法
延续之前关于WCF服务部署到IIS和控制台应用程序的内容,本节介绍如何将WCF服务托管于Windows服务中。该方式具备系统自启动能力,无需人工干预,适合长期稳定运行的服务场景。
1. 创建Windows服务项目
在现有解决方案中新建一个名为 WinSvcHost 的Windows服务项目。
2. 引用必要组件
- 添加对
System.ServiceModel的引用。 - 引用已有的WCF服务类库项目(如
WcfServiceLib)。
3. 实现服务宿主逻辑
创建服务类并重写启动与停止方法,代码结构如下:
using System;
using System.ServiceModel;
using System.ServiceProcess;
namespace WinSvcHost
{
public partial class WcfHostService : ServiceBase
{
private const string SERVICE_NAME = "WcfHostViaWindowsService";
private ServiceHost _host;
public WcfHostService()
{
InitializeComponent();
ServiceName = SERVICE_NAME;
}
protected override void OnStart(string[] args)
{
try
{
_host = new ServiceHost(typeof(BookService));
if (_host.State != CommunicationState.Opened)
_host.Open();
Log($"{SERVICE_NAME} 服务已于 {DateTime.Now} 启动。");
}
catch (Exception ex)
{
Log($"启动失败: {ex.Message}");
throw;
}
}
protected override void OnStop()
{
_host?.Close();
_host = null;
Log($"{SERVICE_NAME} 服务已停止。");
}
private static void Log(string message) => Console.WriteLine(message);
}
}
4. 添加安装程序支持
右键服务设计界面,选择"添加安装程序",系统会自动生成 ProjectInstaller.cs 文件。
5. 配置安装器属性
- 设置
serviceInstaller1的ServiceName和Description。 - 设置
serviceProcessInstaller1的账户类型(如 LocalSystem 或 NetworkService)。
6. 实现命令行安装/卸载功能
修改主程序入口,支持通过参数安装或卸载服务:
using System;
using System.Configuration.Install;
using System.Reflection;
using System.ServiceProcess;
namespace WinSvcHost
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
ServiceBase.Run(new ServiceBase[] { new WcfHostService() });
}
else if (args[0].Equals("/i", StringComparison.OrdinalIgnoreCase))
{
InstallService();
}
else if (args[0].Equals("/u", StringComparison.OrdinalIgnoreCase))
{
UninstallService();
}
}
static void InstallService()
{
if (!ServiceExists("WcfHostViaWindowsService"))
{
var installer = new AssemblyInstaller(Assembly.GetExecutingAssembly().Location, null);
installer.Install(null);
installer.Commit(null);
var controller = new ServiceController("WcfHostViaWindowsService");
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
Console.WriteLine("服务安装并启动成功。");
}
}
static void UninstallService()
{
if (ServiceExists("WcfHostViaWindowsService"))
{
var installer = new AssemblyInstaller(Assembly.GetExecutingAssembly().Location, null);
installer.Uninstall(null);
Console.WriteLine("服务卸载完成。");
}
}
static bool ServiceExists(string serviceName)
{
return ServiceController.GetServices()
.Any(s => s.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));
}
}
}
7. 配置WCF服务端点
在 App.config 中配置服务行为和终结点:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ExposeMetadata">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080/BookSvc/metadata" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WcfServiceLib.BookService" behaviorConfiguration="ExposeMetadata">
<endpoint address="http://localhost:8080/BookSvc"
binding="wsHttpBinding"
contract="WcfServiceLib.IBookService" />
</service>
</services>
</system.serviceModel>
</configuration>
8. 创建批处理脚本
编写两个批处理文件用于快速操作:
REM install.bat
WinSvcHost.exe /i
pause
REM uninstall.bat
WinSvcHost.exe /u
pause
9. 验证安装与运行
执行安装脚本后,打开"服务"管理器,应能看到新注册的服务项。启动服务后,可使用先前开发的客户端程序调用其接口进行测试。