windows服务的现实

  首先什么是windows服务呢?

  Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。  

  在以前的想要实现windows服务,需要强大的c或c++的功力,但是由于.netframework是的强大的功能,我们可以只用少许代码即可实现一个windows服务。但是作为一个专业的程序员,我们不能不求甚解,所以我决定分析一下windows服务的内在过程。

  一个windows服务程序是在windows操作系统下能完成特定功能的可执行的应用程序。windows服务程序虽然是可执行的, 但是它不像一般的可执行文件通过双击就能开始执行,它必须有特定的启动方式。这些启动方式包括了自动启动和手动启动两种。对于自动启动的windows服务程序,它们在windows启动或是重启之后用启登录之前就开始执行了。只要你将相应的windows服务程序注册到服务控制管理器中,并将其启动类别设为自动启动就行了。而对于手动启动的windows服务程序,你可以通过命令行工具的net start命令来启动它,或是通过控制面板工具下的服务一项来启动相应的windows服务程序。同样,一个windows服务程序也不能像一般的应用程序那样被终止。因为windows服务程序一般是没有用户界面的,所以你也要通过命令行工具或是下面图中的工具来停止它,或是在系统关闭时使得windows服务程序自动停止。因为windows服务程序一般是没有用户界面的,所以基于用户界面的api函数对其是没有多大的意义。为了能使一个windows服务程序能够正常并有效在系统环下工作,程序员必须实现一系列的方法来完成其服务功能。windows服务程序应用范围很广,典型的windows服务程序包含了硬件控制、应用程序监视、系统级应 用、诊断、报告、web和文件系统服务等功能。

  好了,在了解了windows服务相关概念之后,我们再看看如何制作一个windows服务程序。首先我们新建一个windows服务。

  当你生成了这个类以后,你会发现这个类已经继承了System.ServiceProcess.ServiceBase这个类。ServiceBase本身有多个虚方法,Onstart()和OnStop()方法是一定要覆盖的。而OnPause(),OnConitnue()是看你个人需要。
  我们在Service1中加Timer组件,并且在InitializeComponent()中加入执行初始化。
private System.ComponentModel.Container components = null;

private void InitializeComponent()
{
  this.timer1 = new System.Timers.Timer(3000);
      ((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
       //
       //Connection 
       //
       this.connstr = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
       this.conn = new System.Data.SqlClient.SqlConnection(this.connstr);
       //
       //timer1
       //
       this.timer1.Enabled = true;
       this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.time1_Elapsed);
        // 
        // Service1
        // 
        this.ServiceName = "Service1";

        ((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();

}

  执行完初始化后,你还可以指定ServiceBase类的属性,CanPauseandContinue,CanStop是允许暂停并恢复和允许停止的意思。

  要使得一个windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点。在windows服务程序中,我们也是在Main()函数中完成这个操作的。首先我们在Main()函数中创建一个windows服务的实例,该实例应该是ServiceBase类的某个子类的对象,然后我们调用由基类ServiceBase类定义的一个Run()方法。然后Run()方法并不就开始了windows服务程序,我们必须通过前面提到的服务程序中同时启动多个服务,那么只要在Main()函数中定义多个ServiceBase类的子类的实列对象就可以了,方法就是创建一个ServiceBase类的数据对对象,使得其中的每个对象对应于某个我们已预先定义好的服务。

static void Main()
{
  ServiceBase[] ServicesToRun;
      ServicesToRun = new ServiceBase[] 
    { 
      new Service1() 
    };
      ServiceBase.Run(ServicesToRun);
}

  然后我们再来定义windows服务的具体内容,

private System.Timers.Timer timer1;
        private string connstr=null;
        private SqlConnection conn = null;
        /// <summary>
        /// 必需的设计变量
        /// </summary>

        public Service1()
        {
            InitializeComponent();
            this.CanPauseAndContinue = true;
            this.CanStop = true;
            this.timer1.Enabled = false;
        }      

        protected override void OnStart(string[] args)
        {
            this.timer1.Enabled = true;
            this.conn.Open();
            this.LogMessage("Service Started");
        }

        protected override void OnStop()
        {
            this.timer1.Enabled = false;
            this.LogMessage("Service Stopped");
            this.conn.Close();
        }

        protected override void OnPause()
        {
            this.timer1.Enabled = false;
        }

        protected override void OnContinue()
        {
            this.timer1.Enabled = true;  
        }

        private void LogMessage(string xMsg)
        {
            try
            {
                //string connstr = ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
                //SqlConnection conn = new SqlConnection(connstr);
                SqlCommand cmd = new SqlCommand("usp_Info_Insert",this.conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new SqlParameter("xMsg",xMsg));
                cmd.ExecuteNonQuery();
            }
            catch (Exception)
            {               
                throw;
            }
        }

        private void time1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            LogMessage("检查服务运行!");
        }

  这就是windows服务的具体内容,但是这是不够滴,因为windows服务想要正常运行,还需要安装程序。其实也很简单。

1. 将这个服务程序切换到设计视图
2. 右击设计视图选择“添加安装程序”
3. 切换到刚被添加的ProjectInstaller的设计视图
4. 设置serviceInstaller1组件的属性:
1) ServiceName = My Sample Service
2) StartType = Automatic
5. 设置serviceProcessInstaller1组件的属性
1) Account = LocalSystem
6. 生成解决方案

然后用installutill.exe命令来安装就可以了。

1. 打开Visual Studio .NET命令提示
2. 改变路径到你项目所在的bin\Debug文件夹位置(如果你以Release模式编译则在bin\Release文件夹)
3. 执行命令“InstallUtil.exe MyWindowsService.exe”注册这个服务,使它建立一个合适的注册项。
注意:直接运行 InstallUtil.exe 可能会失败,提示:
'InstallUtil.exe' 不是内部或外部命令,也不是可运行的程序或批处理文件。
您可以在 C:\WINNT\Microsoft.NET\Framework\v1.1.4322 找到这个可执行程序
4. 右击桌面上“我的电脑”,选择“管理”就可以打计算机管理控制台
5. 在“服务和应用程序”里面的“服务”部分里,你可以发现你的Windows服务已经包含在服务列表当中了
6. 右击你的服务选择启动就可以启动你的服务了。

最后你还可以调试window服务

从另外的角度度看,调试Windows服务绝不同于一个普通的应用程序。调试Windows服务要求的步骤更多。服务不能象你对普通应用程序做的那样,只要简单地在开发环境下执行就可以调试了。服务必须首先被安装和启动,这一点在前面部分我们已经做到了。为了便于跟踪调试代码,一旦服务被启动,你就要用Visual Studio把运行的进程附加进来(attach)。记住,对你的Windows服务做的任何修改都要对这个服务进行卸载和重安装。

为了调试程序,有些附加Windows服务的操作说明。这些操作假定你已经安装了这个Windows服务并且它正在运行。

1. 用Visual Studio装载这个项目
2. 点击“调试”菜单
3. 点击“进程”菜单
4. 确保 显示系统进程 被选
5. 在 可用进程 列表中,把进程定位于你的可执行文件名称上点击选中它
6. 点击 附加 按钮
7. 点击 确定
8. 点击 关闭
9. 在timer1_Elapsed方法里设置一个断点,然后等它执行

posted @ 2011-04-22 15:45  晓炜  阅读(522)  评论(1编辑  收藏  举报