C#编写Windows服务并安装与启动

时间:2022-08-29 07:44:27
   Windows服务可在系统启动时自动打开的程序,非常适合做后台处理程序。
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秒内完成)。
  • 加载完成后,等待一下(等待睡眠完成),程序跳到断点上,然后就可调试了。
    当然除了上面的方法外,还可以写日志、写文件来调试。