1)、创建Windows服务项目
在新建项目中,选择Windows服务。
实现里面的OnStart与OnStop,同时添加对应的事务操作流程即可。如果有其他需求,可以在属性中设置(如暂停等)然后重载对应接口即可。
OnStart中不能做太费时间的操作(如果30s内不能完成,Windows就认为启动失败),所以如果有复杂的操作,需要通过线程完成,同时尽快从OnStart中返回。
OnStart可就收一个字符串数组参数,在启动时,可通过ServiceController.Start(。。。)传入。
2)、添加安装程序
在服务的设计界面上右击,从弹出菜单中选择‘添加安装程序’即可添加安装相关功能。在安装的设计界面上,设置ServiceInstaller相关属性(主要是服务名称ServiceName和启动类型StartType)以及ServiceProcessInstaller相关属性(主要是安装账户Account)。
安装账户如果设为User,则需要设定登录名( 为./+账户的格式)与登录口令,否则安装是会弹出口令输入验证对话框。如果是其他类型的安装账户,在需要注意权限的问题(可能会出现客户端访问被拒绝的情况)。
3)、安装与写作
最简单的方式是通过InstallUtil命令(通过启动SDK命令界面,即可直接使用此命令),但是不适合自动安装实现。
下面介绍一下编码实现。通过反射实现的,所以实现的服务中必须通过上面的第二版添加安装程序。安装与卸载时,需要先判断服务是否已安装。_strLogSrvName为服务名称。
private bool IsSrvExisted(string strSrvName_)
{
try
{
ServiceController srvCtrl = new ServiceController(strSrvName_);
ServiceControllerStatus euStatu = srvCtrl.Status;
return true;
}
catch (SystemException){}
return false;
// ServiceController[] srvCtrls = ServiceController.GetServices();
// foreach (ServiceController srv in srvCtrls)
// {
// if (srv.ServiceName == strSrvName_)
// return true;
// }
//
// return false;
}
public static void Install(string strSrvFile_)
{
if (IsSrvExisted(_strLogSrvName))
{
return;
}
System.Collections.Hashtable hashState = new System.Collections.Hashtable();
AssemblyInstaller asInst = new AssemblyInstaller();
asInst.UseNewContext = true;
asInst.Path = strSrvFile_;
asInst.Install(hashState);
asInst.Commit(hashState);
}
public static void Uninstall(string strSrvFile_)
{
if (IsSrvExisted(_strLogSrvName))
{
AssemblyInstaller asInst = new AssemblyInstaller();
asInst.UseNewContext = true;
asInst.Path = strSrvFile_;
asInst.Uninstall(null);
}
}
4)、服务启动与停止
看通过Windows服务管理器来方便的启动(如果启动时需要参数,此方式不行)与停止
public static void Start(int nOsId_, string strDBConfigFile_)
{
ServiceController srvCtrl = new ServiceController(_strLogSrvName);
if ((srvCtrl.Status == ServiceControllerStatus.Stopped)
|| (srvCtrl.Status == ServiceControllerStatus.StopPending))
{
srvCtrl.Start(new string[] { nOsId_.ToString(), strDBConfigFile_ });
// Wait for 30 seconds
srvCtrl.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30));
}
}
public static void Stop()
{
ServiceController srvCtrl = new ServiceController(_strLogSrvName);
if ( (srvCtrl.Status != ServiceControllerStatus.Stopped)
&& (srvCtrl.Status != ServiceControllerStatus.StopPending))
{
srvCtrl.Stop();
}
}
5)、服务调试
以上就完成了一个基本服务的编写,但是服务不能交互,如何调试呢?
为了方便调试,需要在 Onstart中添加一条睡眠20秒(Sleep)语句:
- 程序编译好,没问题;安装
- 在服务程序中设定断点(要在Sleep后面)
- 启动服务。
- 在IDE的‘调试’-‘附加到进程’中选择我们的服务进程(需要保证20秒内完成)。
- 加载完成后,等待一下(等待睡眠完成),程序跳到断点上,然后就可调试了。