C# Windows Service服务的创建和调试

时间:2016-05-05 01:57:12   收藏:0   阅读:5751

前言

  关于Windows服务创建和调试的文章在网络上的很多文章里面都有,直接拿过来贴在这里也不过仅仅是个记录,不会让人加深印象。所以本着能够更深刻了解服务项目的创建和调试过程及方法的目的,有了这篇记录。

目录

一、什么是Windows Service服务?
二、基于C#的Windows Service服务的创建、安装、卸载?
三、Windows Service服务开发过程中如何调试代码?

正文

一、什么是Windows Service服务?
  Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使 用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上 下文中运行服务。(百度百科)
 
二、基于C#的Windows Service服务的创建、安装、卸载?
  1、打开:Visual Studio 2010 => 新建 => 项目 => Windows 服务,如图:
  技术分享
  步骤:3.设置项目名称    4.设置项目文件夹所在磁盘位置
 
  2、重命名Service1.cs文件名为容易识别功能的文件名,这里我重命名成 MyFirstWinService.cs 。 在此文件的设计视图中右键,在弹出的菜单中选择添加安装程序。
  技术分享
 
  3、项目会自动生成安装文件 ProjectInstaller.cs ,并且分别设置 serviceIntaller1 与 serviceProcessInstaller1 的属性。
  技术分享
  技术分享技术分享
 
  到这里,服务的安装程序与框架已经搭建完毕,然后就在服务类 MyFirstWinService.cs 的代码视图中编写自己的业务代码即可,如下面的代码。
 
  4、服务类 MyFirstWinService.cs 内的代码
技术分享
 1 using System;
 2 using System.ServiceProcess;
 3 
 4 namespace WindowsServiceTest
 5 {
 6     public partial class MyFirstWinService : ServiceBase
 7     {
 8         public MyFirstWinService()
 9         {
10             InitializeComponent();
11         }
12 
13         protected override void OnStart(string[] args)
14         {
15             string str = "服务开启";
16             TestClass.WriteMsgToFile(@"E:\MyProjects\WSExample.txt", str + ",时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
17         }
18 
19         protected override void OnStop()
20         {
21             string str = "服务停止";
22             TestClass.WriteMsgToFile(@"E:\MyProjects\WSExample.txt", str + ",时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
23         }
24 
25         protected override void OnContinue()
26         {
27             string str = "服务继续运行";
28             TestClass.WriteMsgToFile(@"E:\MyProjects\WSExample.txt", str + ",时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
29         }
30 
31         protected override void OnPause()
32         {
33             string str = "服务暂停";
34             TestClass.WriteMsgToFile(@"E:\MyProjects\WSExample.txt", str + ",时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
35         }
36     }
37 
38     public static class TestClass
39     {
40         public static void WriteMsgToFile(string fileName, string content)
41         {
42             using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName, true))
43             {
44                 sw.WriteLine(content);
45             }
46         }
47     }
48 }
View Code
 
  5、在上面的步骤中,已经完成了服务的开发工作。接下来就是服务的安装过程:
  1)安装服务的CMD命令:%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe WindowsServiceTest.exe
  2)卸载服务的CMD命令:%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u WindowsServiceTest.exe
    不过在这里我把命令操作写成两个批处理文件:
Install.bat
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe WindowsServiceTest.exe
Net Start ServiceTest
Uninstall.bat
net stop ServiceTest
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u WindowsServiceTest.exe
  将批处理文件放入项目的bin->Debug文件夹下面,这样就可以方便安装和卸载服务了。当然,写成批处理文件,也方便使用程序控制服务的安装和卸载。
  技术分享
 
 
三、Windows Service服务开发过程中如何调试代码?
  对于有一定C#基础的初学者来说,使用Visual Studio创建并完成一个简单的服务程序,相对来说还是比较容易的。但是对于如何调试Windows服务程序,还是比较麻烦的。主要是Windows服务程序没有办法像其他Windows程序一样直接在代码里面设置断点,按F5来启动代码调试。
  经过查找资料,并亲自进行调试之后,得出三个方法:
方法1:写日志
  这是最传统的调试方法,也是很多程序开发调试代码很常见的。只是这个方法不能实时观察数据在代码里面的变化,只能在你认为可能出现错误的地方添加写日志的方法,把数据变化过程记录下来。
 
方法2:附加进程
  这是Windows服务开发常用的调试方式。此方法必须先把写好的服务进行编译生成可执行的exe安装程序,并安装启动服务后,才可以进行附加此服务进程。
  1、首先要对服务进行安装,然后启动服务。
  2、打开VS项目,选择菜单 调试->附加到进程 选项,选择你的服务进程(如果找不到可以勾选 显示所有用户进程 选项)就可以了。如下图:
  技术分享
  这里有一个问题:就是在附加到进程的同时 OnStart 函数已经执行完毕,所以对 Onstart 无法调试。这个可以通过设置启动服务延时来加载调试。
技术分享
        private System.Timers.Timer timerDelay;
        protected override void OnStart(string[] args)
        {
            try
            {
                ///delay start the SynData 30seconds
                timerDelay = new System.Timers.Timer(30000);   
                timerDelay.Elapsed += new System.Timers.ElapsedEventHandler(timerDelay_Elapsed);
                timerDelay.Start();
            }
            catch (Exception ex)
            {
                this.PrintExceptions(ex);
            }
        }

        void timerDelay_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timerDelay.Enabled = false;
            timerDelay.Close();
            
            //你要加的代码
            string str = "服务开启";
            TestClass.WriteMsgToFile(FilePath, str + ",时间:" + DateTime.Now.ToString(DateFormat));
        }
View Code
  注意:正常服务的启动时间为30秒左右,当服务启动时间超过30秒会报错!,所以不要在OnStart中做过多的操作,也可以用这种延时的方法启动服务,以防在启动服务时超时。
 
方法3:修改Main函数中的起始代码
  这是一个取巧的方法,在Main函数中,注释掉原有自动生成的代码,手动实例化所写的服务类。如下代码中红色部分:
      static class Program
     {
         /// <summary>
         /// 应用程序的主入口点。
         /// </summary>
         static void Main()
         {
             //ServiceBase[] ServicesToRun;
             //ServicesToRun = new ServiceBase[]
             //{
             //    new ServiceTest()
             //};
             //ServiceBase.Run(ServicesToRun);

             ServiceTest st = new ServiceTest(); //ServiceTest为自己建的服务类
             st.OnStart();
         }
     }
  然后需要把ServiceTest类中的 protected override void OnStart(string[] args)修改为 public void OnStart(),接着就可以在OnStart()方法里面设置断点,按F5运行调试了。
        public void OnStart()
        {
            string str = "服务开启";
            TestClass.WriteMsgToFile(FilePath, str + ",时间:" + DateTime.Now.ToString(DateFormat));
            //Code Something......
        }
  ServiceTest类中的其他方法也可以这样进行调试,待调试完毕后,把方法再修改回原来的样子既可。
 
一点补充:
1)Service启动属性:
    Manual      服务安装后,必须手动启动。
    Automatic    每次计算机重新启动时,服务都会自动启动。
    Disabled     服务无法启动。
 
2)新建的Service项目,其中各属性的含义(服务类 MyFirstWinService.cs 设计视图->右键属性):
    Autolog   是否自动写入系统的日志文件
    CanHandlePowerEvent   服务时候接受电源事件
    CanPauseAndContinue   服务是否接受暂停或继续运行的请求
    CanShutdown   服务是否在运行它的计算机关闭时收到通知,以便能够调用 OnShutDown 过程
    CanStop   服务是否接受停止运行的请求
    ServiceName   服务名
 
3) 也可以在系统服务管理器中,设置相应Service的属性或启动方式等 
    计算机管理 -> 服务和应用程序  -> 服务  -> ...
 
 
  这些只是我目前知道的调试方法,当然肯定还有,有时候还需要多种方法结合着来调试。
 
评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!