读书人

怎么创建一个标准的Windows服务

发布时间: 2012-09-15 19:09:29 作者: rapoo

如何创建一个标准的Windows服务


Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->????[RunInstaller(true)]
????public?class?ListenInstaller?:?Installer
????{
????????private?System.ServiceProcess.ServiceProcessInstaller?serviceProcessInstaller;
????????private?System.ServiceProcess.ServiceInstaller?serviceInstaller;

????????///?<summary>
????????///?必需的设计器变量。
????????///?</summary>
????????private?System.ComponentModel.IContainer?components?=?null;???

????????public?ListenInstaller()
????????{
????????????InitializeComponent();
????????????//重新覆盖设计时赋予的服务名称
????????????this.serviceInstaller.DisplayName?=?Constants.ServiceName;
????????????this.serviceInstaller.ServiceName?=?Constants.ServiceName;
????????}
???????

????????public?override?void?Install(System.Collections.IDictionary?stateSaver)
????????{
????????????base.Install(stateSaver);
????????}


????????private?void?serviceInstaller_AfterInstall(object?sender,?InstallEventArgs?e)
????????{
????????????ServiceController?service?=?new?ServiceController(Constants.ServiceName);

????????????if?(service.Status?!=?ServiceControllerStatus.Running)
????????????{
????????????????try
????????????????{
????????????????????service.Start();
????????????????}
????????????????catch?(Exception?ex)
????????????????{
????????????????????EventLog?loger;
????????????????????loger?=?new?EventLog();
????????????????????loger.Log?=?"Application";
????????????????????loger.Source?=?Constants.ServiceName;
????????????????????loger.WriteEntry(ex.Message?+?"\n"?+?ex.StackTrace,?EventLogEntryType.Error);
????????????????}
????????????}
????????}

????????private?void?serviceInstaller_BeforeUninstall(object?sender,?InstallEventArgs?e)
????????{
????????????ServiceController?service?=?new?ServiceController(Constants.ServiceName);

????????????if?(service.Status?!=?ServiceControllerStatus.Stopped)
????????????{
????????????????try
????????????????{
????????????????????service.Stop();
????????????????}
????????????????catch?(Exception?ex)
????????????????{
????????????????????EventLog?loger;
????????????????????loger?=?new?EventLog();
????????????????????loger.Log?=?"Application";
????????????????????loger.Source?=?Constants.ServiceName;
????????????????????loger.WriteEntry(ex.Message?+?"\n"?+?ex.StackTrace,?EventLogEntryType.Error);
????????????????}
????????????}
????????}
???????? ...............
?????}

2)程序启动
程序的启动很简单,基本上是自动创建服务程序的时候就生成了,这里列出来解析是为了说明服务调试的操作。
程序的启动是在Main函数里面,添加下面的代码即可
Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->????????????ServiceBase[]?ServicesToRun;

????????????ServicesToRun?=?new?ServiceBase[]?{?new?SocketService()?};

????????????ServiceBase.Run(ServicesToRun);
上面是标准的启动代码,但很多时候,我们需要调试服务,因此会加入一个跳转的开关
Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->????????????#region?调试程序时使用的代码
????????????//使用方法:在该Project的属性页,设置输入参数"-T",即可进入下面这段代码,发布时请去掉参数;
????????????if?(args.Length?>=?1?&&?args[0].ToUpper()?==?"-T")
????????????{
????????????????try
????????????????{
????????????????????SocketService?service?=?new?SocketService();
????????????????????service.Execute();
????????????????}
????????????????catch?(Exception?ex)
????????????????{
????????????????????throw?ex;
????????????????}
????????????????return;
????????????}

????????????#endregion上面的操作就是为了可以使用普通的调试功能调试Windows服务,其中的"-T"是在开发工具VS的IDE上设置的一个参数,?如下图所示。
怎么创建一个标准的Windows服务


3)服务操作
首先需要创建一个集成自System.ServiceProcess.ServiceBase的服务类,如SocketService服务类,在SocketService类的构造函数中,您可能需要初始化一些信息,如创建一个定时器,修改服务器类的名称,读取配置参数等信息,以便初始化服务类的参数。
接着您需要重载服务基类的一些函数:OnStart、OnStop、OnContinue、OnPause、OnShutdown和定时器的触发函数timerReAlarm_Elapsed。完整的类如下

Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->????public?class?SocketService?:?ServiceBase
????{
????????private?static?readonly?ILog?logger?=?LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
????????private?AppConfig?appConfig?=?new?AppConfig();
????????private?System.Timers.Timer?timerReAlarm;

????????private?int?ServiceCycle?=?1;//服务运行间隔,和整点运行相斥(单位分钟)
????????private?int?CycleCount?=?0;//间隔的服务运行计数(单位分钟)

????????private?int?ServiceRunAt?=?0;//整点运行服务时间,负数为禁用(单位小时)
????????private?bool?RunAtOnce?=?false;//整点运行服务是否已经运行

????????private?bool?GBLService?=?false;//是否启动GBL同步服务
????????private?bool?DomainService?=?false;//是否启动域用户同步

????????///?<summary>?
????????///?必需的设计器变量。
????????///?</summary>
????????private?System.ComponentModel.IContainer?components?=?null;
????????private?System.Diagnostics.EventLog?eventLog;

????????public?SocketService()
????????{
????????????InitializeComponent();

????????????eventLog?=?new?EventLog();
????????????eventLog.Log?=?"Application";
????????????eventLog.Source?=?Constants.ServiceName;

????????????this.ServiceName?=?Constants.ServiceName;

????????????try
????????????{
????????????????//系统心跳
????????????????int?interval?=?int.Parse(appConfig.AppConfigGet("TimerInterval"));
????????????????interval?=?(interval?<?1)???1?:?interval;//不能太小
????????????????timerReAlarm?=?new?System.Timers.Timer(interval?*?60000);//分钟
????????????????timerReAlarm.Elapsed?+=?new?ElapsedEventHandler(timerReAlarm_Elapsed);

????????????????//服务运行间隔
????????????????ServiceCycle?=?int.Parse(appConfig.AppConfigGet("ServiceCycle"));
????????????????ServiceCycle?=?(ServiceCycle?<?interval)???interval?:?ServiceCycle;//不能小于心跳

????????????????//服务整点运行
????????????????ServiceRunAt?=?int.Parse(appConfig.AppConfigGet("ServiceRunAt"));

????????????????GBLService?=?Convert.ToBoolean(appConfig.AppConfigGet("GBLService"));
????????????????DomainService?=?Convert.ToBoolean(appConfig.AppConfigGet("DomainService"));

????????????????logger.Info(Constants.ServiceName?+?"已初始化完成");
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????logger.Error(Constants.ServiceName?+?"初始化错误",?ex);
????????????}
????????}

????????///?<summary>
????????///?设置具体的操作,以便服务可以执行它的工作。
????????///?</summary>
????????protected?override?void?OnStart(string[]?args)
????????{
????????????logger.Info(Constants.ServiceName?+?"开始启动。");

????????????timerReAlarm.Start();???????????
????????????eventLog.WriteEntry(Constants.ServiceName?+?"已成功启动。",?EventLogEntryType.Information);

????????????CreateTask();
????????}

????????///?<summary>
????????///?停止此服务。
????????///?</summary>
????????protected?override?void?OnStop()
????????{
????????????timerReAlarm.Stop();
????????}

????????///?<summary>
????????///?暂停后继续运行
????????///?</summary>
????????protected?override?void?OnContinue()
????????{
????????????timerReAlarm.Start();
????????????base.OnContinue();
????????}

????????///?<summary>
????????///?暂停
????????///?</summary>
????????protected?override?void?OnPause()
????????{
????????????timerReAlarm.Stop();
????????????base.OnPause();
????????}

????????///?<summary>
????????///?关闭计算机
????????///?</summary>
????????protected?override?void?OnShutdown()
????????{
????????????base.OnShutdown();
????????}

????????private?void?timerReAlarm_Elapsed(object?sender,?System.Timers.ElapsedEventArgs?e)
????????{
????????????CreateTask();
????????}


????????///?<summary>
????????///?使用线程池方式运行程序
????????///?优点:快速启动Windows服务,?在后台继续程序操作.
????????///?</summary>
????????private?void?CreateTask()
????????{
????????????ThreadPool.QueueUserWorkItem(new?WaitCallback(ExecuteTask),?null);
????????}

????????///?<summary>
????????///?开始执行同步任务
????????///?</summary>????
????????private?void?ExecuteTask(object?status)
????????{
????????????try
????????????{
????????????????//采用整点运行方式
????????????????if(ServiceRunAt?>?0)
????????????????{
????????????????????if(DateTime.Now.Hour?==?ServiceRunAt)
????????????????????{
????????????????????????if(!RunAtOnce)
????????????????????????{
????????????????????????????Execute();
????????????????????????????RunAtOnce?=?true;//标识整点已经运行过了
????????????????????????}
????????????????????}
????????????????????else
????????????????????{
????????????????????????RunAtOnce?=?false;
????????????????????}

????????????????}
????????????????else//采用间隔运行方式
????????????????{
????????????????????//不管服务间隔是否心跳的倍数,只要服务间隔时间大于等于间隔时间,就执行一次
????????????????????if(CycleCount?>=?ServiceCycle)
????????????????????{
????????????????????????Execute();
????????????????????????CycleCount?=?0;
????????????????????}
????????????????????else
????????????????????{
????????????????????????CycleCount++;
????????????????????}
????????????????}
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????logger.Error("ExecuteTask()函数发生错误",?ex);
????????????????eventLog.WriteEntry(Constants.ServiceName?+?"运行时出现异常!\r\n"?+?ex.Message?+?"\r\n"?+?ex.Source?+?"\r\n"?+?ex.StackTrace);
????????????}
????????}

????????public?void?Execute()
????????{
????????????//初始化数据库连接
????????????string?DatabasePassword?=?Sys.decode(ConfigurationSettings.AppSettings.Get("DatabasePassword"));
????????????DAO.init(ConfigurationSettings.AppSettings.Get("DatabaseConnect").Replace("{$password}",?DatabasePassword),?DAO.DATABASE_SQLSERVER);?//初始化数据库(SQL?Server)访问对象
????????????Lib.adPasswd?=?Sys.decode(ConfigurationSettings.AppSettings.Get("password"));????
????????????
????????????if(GBLService)
????????????{
????????????????AutomatismXml?xml?=?new?AutomatismXml();
????????????????xml.AutomatismXmlData(0);

????????????????logger.Info(Constants.ServiceName?+?DateTime.Now.ToShortTimeString()?+?"已成功调用了GBLService一次。");
????????????????eventLog.WriteEntry(DateTime.Now.ToShortTimeString()?+?"已成功调用了GBLService一次。",?EventLogEntryType.Information);
????????????}
????????????if(DomainService)
????????????{
????????????????string?msg?=?string.Empty;
????????????????string?path?=?ConfigurationSettings.AppSettings.Get("path");
????????????????string?username?=?ConfigurationSettings.AppSettings.Get("username");
????????????????string?domain?=?ConfigurationSettings.AppSettings.Get("domain");
????????????????AD.init(path,?username,?Lib.adPasswd,?domain);?

????????????????DomainHelper.accountSync(true,?false,?true,?ref?msg,?1);
????????????????Log.saveADLog(null,?"系统同步域用户:"?+?msg);

????????????????logger.Info(Constants.ServiceName?+?DateTime.Now.ToShortTimeString()?+?"已成功调用了DomainService一次。");
????????????????eventLog.WriteEntry(DateTime.Now.ToShortTimeString()?+?"已成功调用了DomainService一次。",?EventLogEntryType.Information);
????????????}
????????}

??????? ...................
????}
4. 使用InstallUtil来安装和卸载服务
安装和卸载Windows服务,需要使用InstallUtil工具类进行操作,该工具是Dotnet框架附带的一个工具,在%SystemRoot%\Microsoft.NET\Framework\*** 对应的目录中。
其中App.config中的内容如下
Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><?xml?version="1.0"?encoding="utf-8"??>
<configuration>
????<appSettings>
????????<!--心跳间隔,系统设置,单位(分钟)-->
????????<add?key="TimerInterval"?value="5"?/>
????????
????????<!--?运行同步服务的间隔时间(单位:分钟)?-->
????????<add?key="ServiceCycle"?value="60"?/>
????????<!--Windows服务在固定时刻(0~23时刻)运行,设置了该参数,同步服务间隔参数无效,负数为禁用-->
????????<add?key="ServiceRunAt"?value="-1"?/>
????????
????????<!--是否启动GBL信息自动同步服务-->
????????<add?key="GBLService"?value="True"?/>
????????<!--是否启动域用户信息自动同步服务-->
????????<add?key="DomainService"?value="True"?/>
????????
????</appSettings>
</configuration>
安装Windows服务的命令如下:
Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->@ECHO?OFF

REM?The?following?directory?is?for?.NET1.1
set?DOTNETFX=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322
set?PATH=%PATH%;%DOTNETFX%

cd\
cd?"%SystemRoot%\..\Program?Files\BornShine\用户信息同步服务"

echo?正在安装?用户信息同步服务
echo?---------------------------------------------------

InstallUtil?/i?AutoSyncService.exe

echo?---------------------------------------------------

echo?Done.
exit

怎么创建一个标准的Windows服务
卸载Windows服务的命令如下:
Code
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->@ECHO?OFF

REM?The?following?directory?is?for?.NET1.1
set?DOTNETFX=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322
set?PATH=%PATH%;%DOTNETFX%

cd\
cd?"%SystemRoot%\..\Program?Files\BornShine\用户信息同步服务"

echo?正在卸载?用户信息同步服务
echo?---------------------------------------------------

InstallUtil?/U?AutoSyncService.exe

echo?---------------------------------------------------

echo?Done.
exit

读书人网 >windows

热点推荐