上接 WCF学习之旅—WCF服务部署到IIS7.5(九)
WCF学习之旅—WCF服务部署到应用程序(十)
七 WCF服务的Windows 服务程序寄宿
这种方式的服务寄宿,和IIS一样有一个一样的优点,系统启动后,WCF服务也会跟着启动了,不用人工干预,也是一种较好的寄宿方式。
(1) 在解决方案下新建控制台输出项目 WinServiceHosting。如下图。
(2)添加 System.ServiceModel.dll 的引用。
(3)添加 WCF 服务类库(WcfServiceLib)的项目引用。
(4) 添加响应的Window服务类。如下图。
(5)然后在服务类启动里面添加WCF的寄宿代码,如下所示。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace WinSvrviceHosting
{
partial class WCFServiceMgr : ServiceBase
{
string Name = "WCF服务Windows Service寄宿";
public WCFServiceMgr()
{
InitializeComponent();
this.ServiceName = Name;
}
protected override void OnStart(string[] args)
{
// TODO: 在此处添加代码以启动服务。
try
{
svrHost = new ServiceHost(typeof(WCFServiceMgr));
if (svrHost.State != CommunicationState.Opened)
{
svrHost.Open();
}
}
catch (Exception ex)
{
Logger.Log(ex,string.Empty,string.Empty,string.Empty);
}
Logger.Log(Name + DateTime.Now.ToShortTimeString() + "已成功调用了服务一次。");
Logger.Log(Name + "已成功启动。");
}
protected override void OnStop()
{
// TODO: 在此处添加代码以执行停止服务所需的关闭操作。
if (svrHost!=null)
{
svrHost.Close();
svrHost = null;
}
}
private static object syncRoot = new Object();//同步锁
private ServiceHost svrHost = null; //寄宿服务对象
}
}
(6) 在WCFServiceMgr.cs的设计界面上右键,在弹出菜单中选择“添加安装程序”。如下图1。这时,项目里会自动生成一个ProjectInstaller.cs文件。如下图2。
图1
图2
( 7) 选中serviceInstaller1,打开它的属性视图,修改属性。如下图所示:
(8) 接着选中serviceProcessInstaller1,打开它的属性视图,修改属性。如下图:(这里服务账号也可以是其他的。)
(9) 为了实现通过该控制台程序实现参数化安装和卸载服务,我们需要拦截控制台的参数,并进行相应的操作,如下所示。
using System; using System.Collections.Generic; using System.Configuration.Install; using System.Linq; using System.ServiceProcess; using System.Text; using System.Threading.Tasks; namespace WinSvrviceHosting { class Program { static void Main(string[] args) { ServiceController service = new ServiceController(WCFServiceMgr.Name); // 运行服务 if (args.Length == 0) { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new WCFServiceMgr() }; ServiceBase.Run(ServicesToRun); } else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i") { #region 安装服务 if (!IsServiceExisted("WCFServiceMgr")) { try { string[] cmdline = { }; string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller(); AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline); transactedInstaller.Installers.Add(assemblyInstaller); transactedInstaller.Install(new System.Collections.Hashtable()); TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10); service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, timeout); } catch (Exception ex) { Logger.Log(ex,string.Empty,string.Empty,string.Empty); throw ex; } } #endregion } else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u") { #region 删除服务 try { if (IsServiceExisted("WCFServiceMgr")) { string[] cmdline = { }; string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller(); AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline); transactedInstaller.Installers.Add(assemblyInstaller); transactedInstaller.Uninstall(null); } } catch (Exception ex) { Logger.Log(ex, string.Empty, string.Empty, string.Empty); throw ex; } #endregion } } #region 检查服务存在的存在性 /// <summary> /// 检查服务存在的存在性 /// </summary> /// <param name=" NameService ">服务名</param> /// <returns>存在返回 true,否则返回 false;</returns> public static bool IsServiceExisted(string NameService) { ServiceController[] services = ServiceController.GetServices(); foreach (ServiceController s in services) { if (s.ServiceName.ToLower() == NameService.ToLower()) { return true; } } return false; } #endregion } }
(10)添加应用程序配置文件App.config,这次我们使用配置的方式进行WCF服务的公布,WCF服务配置代码如下。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <system.serviceModel> <diagnostics> <messageLogging logEntireMessage="true" logKnownPii="false" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" /> <endToEndTracing propagateActivity="true" activityTracing="true" messageFlowTracing="true" /> </diagnostics> <behaviors> <serviceBehaviors> <behavior name="metadataBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8080/BookService/metadata" /> <serviceDebug includeExceptionDetailInFaults="True" /> </behavior> </serviceBehaviors> </behaviors> <services> <service behaviorConfiguration="metadataBehavior" name="WcfServiceLib.BookService"> <endpoint address="http://127.0.0.1:8080/BookService" binding="wsHttpBinding" contract="WcfServiceLib.IBookService" /> </service> </services> </system.serviceModel> </configuration>
(11) 编译程序成功后,我们添加两个批处理的DOS脚本来实现执行程序的自动安装和卸载,如下所示。
--安装脚本 "WinSvrviceHosting.exe" -i pause
--卸载脚本 "WinSvrviceHosting.exe" -u Pause
(12) 我们首先执行安装脚本。结果如下图。
(13) 顺利执行脚本后,“管理工具—》服务”,在服务列表里面就增加一个服务项目了。如下图。
(14) 执行卸载脚本,脚本就会卸载服务。如下图。
建立客户端
使用我们在Console寄宿程序编写的客户端,去访问Windows窗体宿主程序的WCF服务。