• WindowS服务(C#)


    目录:

    1:创建windows服务;

    2:如何动态的设置windows服务的名称;

    3:如何调试windows服务;


     一:创建windows服务:

    Windows服务在Visual Studio 以前的版本中叫NT服务,在VS.net启用了新的名称。用Visual C# 创建Windows服务不是一件困难的事,本文就将指导你一步一步创建一个Windows服务并使用它。这个服务在启动和停止时,向一个文本文件中写入一些文字信息。

    第一步:创建服务框架
    要创建一个新的 Windows 服务,可以从Visual C# 工程中选取 Windows 服务(Windows Service)选项,给工程一个新文件名,然后点击 确定。
    你可以看到,向导向工程文件中增加WebService1.cs类

    其中各属性的含意是:

    ü         Autolog                 是否自动写入系统的日志文件

    ü         CanHandlePowerEvent     服务时候接受电源事件

    ü         CanPauseAndContinue          服务是否接受暂停或继续运行的请求

    ü         CanShutdown 服务是否在运行它的计算机关闭时收到通知,以便能够调用 OnShutDown 过程

    ü         CanStop                              服务是否接受停止运行的请求

    ü         ServiceName                       服务名

    第二步:向服务中增加功能
    在 .cs代码文件中我们可以看到,有两个被忽略的函数 OnStart和OnStop。

     1 protected override void OnStart(string[] args)
     2 
     3 {
     4 
     5  FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write); 
     6 
     7 StreamWriter m_streamWriter = new StreamWriter(fs); 
     8 
     9 m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); 
    10 
    11 m_streamWriter.WriteLine("mcWindowsService:         Service Started"+DateTime.Now.ToString()+"\n"); 
    12 
    13 m_streamWriter.Flush();
    14 
    15 m_streamWriter.Close();
    16 
    17 fs.Close();
    18 
    19  
    20 
    21 }
    22 
    23  
    24 
    25 protected override void OnStop()
    26 
    27 {
    28 
    29 FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write); 
    30 
    31 StreamWriter m_streamWriter = new StreamWriter(fs); 
    32 
    33 m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); 
    34 
    35 m_streamWriter.WriteLine(" mcWindowsService: Service Stopped "+DateTime.Now.ToString()+"\n"); 
    36 
    37 m_streamWriter.Flush();
    38 
    39 m_streamWriter.Close();
    40 
    41 fs.Close();
    42 
    43 

    第三步: 将安装程序添加到服务应用程序

    Visual Studio.NET 随附有安装组件,可用来安装与服务应用程序相关联的资源。安装组件在正在安装到的系统上注册一项单个的服务,并使服务控制管理器知道该服务的存在。

    要正确安装服务,并不需要在安装程序中进行任何特殊编码。但是,如果需要向安装进程添加特殊功能,则可能偶尔需要修改安装程序的内容。

           将安装程序添加到服务应用程序的步骤是:

    1:在解决方案中,访问要向其中添加安装组件的服务的Design视图。

    2:在属性窗口中,单击添加安装程序链接

    这时项目中就添加了一个新类 ProjectInstaller 和两个安装组件 ServiceProcessInstaller 和 ServiceInstaller,并且服务的属性值被复制到组件。

    3:若要确定如何启动服务,请单击 ServiceInstaller 组件并将 StartType 属性设置为适当的值。

    ü         Manual      服务安装后,必须手动启动。

    ü         Automatic    每次计算机重新启动时,服务都会自动启动。

    ü         Disabled     服务无法启动。

    4:将serviceProcessInstaller类的Account属性改为 LocalSystem

         这样,不论是以哪个用户登录的系统,服务总会启动。

    第四步:生成服务程序

    通过从生成菜单中选择生成来生成项目。

    注意   不要通过按 F5 键来运行项目——不能以这种方式运行服务项目。

    第五步:安装服务

    访问项目中的已编译可执行文件所在的目录。 
    用项目的输出作为参数,从命令行运行 InstallUtil.exe。在命令行中输入下列代码: 
    installutil yourproject.exe
    卸载服务

    用项目的输出作为参数,从命令行运行 InstallUtil.exe。

    installutil /u yourproject.exe
     
     
    至此,整个服务已经编写,编译,安装完成,你可以在控制面板的管理工具的服务中,看到你编写的服务。

     
     

    动态设置Windows服务的名称

    意图

      由于项目的需求,要在Windows里把同样的组件(不同的拷贝)制作成多个不同名称的服务,这些服务完成相同的功能。

     方案

    方案一:

     再看看Windows服务的项目:有一个xxxService.cs的类,一个xxxServiceInstaller.cs的类

    在前一个类中可以设置你的服务的ServiceName,后一个类中指定安装时要安装哪个ServiceName的服务。这两个ServiceName必须相同。

    可以这样设想:在安装时,安装工具产生了一系列的对象以执行安装注册服务的过程,其中就包括了ServiceInstaller的对象,以及Service对象。(这个安装过程是注册Windows服务范畴,与这个服务完成的功能无关。)你不是要构造对象吗?于是,我们可以在ServiceInstaller的构造函数里指定要安装的Service的ServiceName,同时在Service的构造函数里指定自己的ServiceName,只要两者一致就可以让安装过程顺利完成。再仔细看看项目的代码,这两个类设置ServiceName的地方确实在构造函数中。

     来个最简单的,用.txt文件来指定服务名称。

          建立一个文本文件ServiceName.txt存放Windows服务的名称。

          在代码中添加一个函数GetServiceName从文件中获取名称:

    代码

    在两个类的构造函数中分别设置ServiceName为GetServiceName()。

    编译,设置ServiceName.txt的文本值为“服务一”,注册时,运行InstallUtil.exe WindowsService1.exe,“服务一”注册成功。

          把程序组件拷贝一份到新的目录下,改变ServiceName.txt的文本值为“服务二”,运行InstallUtil.exe WindowsService1.exe,“服务二”注册成功。

          这样我的程序就可以拷贝到天涯海角,然后改变ServiceName.txt的值就可以注册成无数的服务了

    方案二:

    使用命令行命令的SC 命令

    你在复制这个程序后
    可以使用如下命令创建一个服务
    连xxxServiceInstaller都不用建了

    SC CREATE 服务名 BINPATH= "你的exe的完整路径"

    完全手打 如果有误可以查询命令行的帮助

    方案三:

    代码
    public ProjectInstaller()
    {
    InitializeComponent();
    this.serviceInstaller1.Description = XmlUnit.GetText(AppDomain.CurrentDomain.BaseDirectory + "Services.xml""Services/Service/Description");
    this.serviceInstaller1.DisplayName = XmlUnit.GetText(AppDomain.CurrentDomain.BaseDirectory + "Services.xml""Services/Service/DisplayName");
    this.serviceInstaller1.ServiceName = XmlUnit.GetText(AppDomain.CurrentDomain.BaseDirectory + "Services.xml""Services/Service/ServiceName");
    }
    弄个配置文件:Services.xml
    格式如:
    <Services>
    <Service>
    <ServiceName>AiBoSM</ServiceName>
    <DisplayName>爱博短信发送</DisplayName>
    <Description>自动启动爱博短信发送应用程序</Description>
    <Path>E:\VSS\综合办公平台\验收资料\短信平台相关资料\电信\爱博企信通中间件SQL\smssql_20080711.exe</Path>
    <Interval>60</Interval>
    </Service>
    </Services>

    三:调试Windows服务技巧:

    当windows服务创建好后,有时会因为业务逻辑出错导致windows服务无法启动,这时我们就要想办法来通过调试来找出有问题的代码来,windows服务不同于一般的应用程序的调试方式,当我们按F9设置好断点后,按F5来运行调试时,会提示一个错误,那么怎么才能调试windows服务呢,很简单:

    代码
    修改以下代码:
    namespace
     BoxService
    {
        
    static class
     Program
        {
            
    /// <summary>

            
    /// 应用程序的主入口点。
            
    /// </summary>

            static void Main()
            {
                ServiceBase[] ServicesToRun;

                
    //
     同一进程中可以运行多个用户服务。若要将
                
    //
     另一个服务添加到此进程中,请更改下行以
                
    //
     创建另一个服务对象。例如,
                
    //

                
    //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
                
    //

                
    //测试 
                BoxDataService bds = new BoxDataService();
                bds.OnStart();
             
                
            }
        }
    }
    //将此方法:
    protected override void OnStart(string[] args)
            {
                 ...
           
            }
    //更改为:

    protected void    OnStart()
            {
                 ...
           
            }

    只要上述方法能成功执行,那么服务一般都会启动成功;

    如果服务里面使用了多线程,那么调试多线程时可以采用附加我们刚创建并且已启动的服务的进程即可调试;

    参考文章:http://www.cnblogs.com/zhangyf/archive/2009/06/04/1496154.html

  • 相关阅读:
    centos7安装doxygen
    mysql和mariadb支持insert delayed的问题
    Ubuntu用android-ndk-r15c编译boost_1_65_1
    记不住的Android活动的生命周期
    SpringBoot——经典的Hello World【二】
    SpringBoot——报错总结
    SpringBoot——SpringBoot学习记录【一】
    Nginx——配置文件服务下载
    CRAP-API——如何在Linux服务器部署CRAP-API教程
    Linux—— 报错汇总
  • 原文地址:https://www.cnblogs.com/zhangzt/p/1808031.html
Copyright © 2020-2023  润新知