如何正确编程Windows服务?

时间:2014-03-25 09:56:20

标签: c# windows service

我在MSDN上阅读有关Windows服务的一些有趣内容,但是我在掌握一些信息方面遇到了一些麻烦。

我按照this msdn page的步骤创建了一个Windows服务,我注意到他们忽略了一个自动生成的部分(即program.cs中的主要部分)启动了一组服务。我无法理解服务实际运行的方式,或者更准确地说,我如何正确地编写服务来执行我想要的操作。自动生成的service.cs只有一个构造函数,一个OnStart和OnStop事件方法。我应该在OnStart方法上编写大部分代码,还是有与服务类似的Main部分?

我的另一个问题是关于服务的部署。在我提到的页面中,他们引用了另一个让我在VS开发人员控制台上使用installutil的页面。如果目标平台没有开发人员控制台,我该如何为服务创建自动安装程序?

2 个答案:

答案 0 :(得分:2)

服务不过是(大多数时候)控制台程序。所以,是的,OnStart方法是您的服务的入口点,就像Main方法一样。如果必须定期执行服务,则必须管理循环部分。只要用户手动停止服务或系统执行,就会调用OnStop方法。 在Main Program方法中启动ServiceBase数组的原因是,您可以拥有多个服务类并并行启动它们。 您必须知道Main方法的内容只能由系统在已安装服务的上下文中执行。你无法以这种方式调试。你必须使用经典的#34;控制台应用程序"来完成它。我个人使用技巧来更轻松地调试VisualStudio中的服务:

  • 假设我们有一个ImportService类来执行我们的处理。我们将使用DEBUG编译器常量并创建一个将开始处理的DebugStart()方法(OnStart方法受到保护)

    #if DEBUG
       public void DebugStart()
       {
          // Call you processing method
       }
    #endif
    
  • 现在让我们编辑我们的Main()程序方法,以便在调试时开始我们的处理而不是ServiceBase.Run方法:

    #if DEBUG
        ImportService service = new ImportService();
        service.DebugStart();
    #else
        ServiceBase[] ServicesToRun =
        { 
            new ImportService() 
        };
        ServiceBase.Run(ServicesToRun);
    #endif
    

这样,在调试模式下运行项目时,它将作为标准控制台程序启动服务。 installutil命令是用于安装服务程序的windows命令。要安装您的服务,您有多种解决方案,具体取决于您的安装程序:

  • 使用InstallShield。自Visual Studio 2013(或2012年?)以来,InstallShield Lite Edition标准地包含在以前的Windows Installer中。您必须激活并安装它(创建其他类型的新项目>配置和部署>激活InstallShield限制版)。您可以使用安装程序
  • 的形式安装Windows服务
  • 制作一个简单的.bat文件,该文件将在客户端计算机上运行installutil命令。
  • 使用WiX非常完整但也更复杂但允许您在安装过程中执行任何操作。

答案 1 :(得分:1)

  

如果目标平台没有开发人员控制台,我如何为服务制作自动安装程序?

您必须添加System.Configuration.Install.Installer才能在远程计算机上安装服务。如果目标机器没有开发人员控制台,这甚至可以工作。

  

我无法理解服务的实际运行方式,或者   更正确的是,我如何正确编程服务来做我的事情   想。

这实际上比你最初想的要简单得多。您的服务将与正常流程一样运行。如果您有一个打开端口并监听流量的控制台应用程序,那么当您将其转换为服务时,它仍然可以以相同的方式工作。

但是,更改服务的启动方式会有什么变化。正确安装服务后,可以这样启动:

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

YourServerClass应该继承ServiceBase,这样您就可以使用OnStartOnStop方法。在这些方法中,您可以指定服务的启动方式,以及停止服务时应执行的操作(在清理等方面)。

如果一切顺利,并且您在项目中拥有installetr和实际服务,那么您应该能够install it as a service through the use of PowerShell,之后您可以像在服务窗口中一样启动,停止并重新启动它与任何其他服务。