2012-07-30 93 views
1

我有一个C#应用程序,它使用的Windows服务并非总是处于启动状态,我希望能够在服务启动和关闭时发送电子邮件通知。我写了电子邮件脚本,但我似乎无法弄清楚如何检测服务状态更改。检测/监听服务启动和停止状态更改

我一直在阅读 ServiceController类,我认为 WaitForStatus()方法可能是我需要的,但是我一直未能找到一个示例,它在尚未启动的服务上使用。 编辑:由于WaitForStatus()方法busy-waiting,我需要执行由服务运行的程序的其余部分,同时收听服务启动/停止,我不认为这是方法我,除非有人使用这种方法结合多线程的解决方案,并且干净而高效。

 

更多:

  • 该服务将不会被应用程序启动 - 应用程序的用户将在管理工具的服务窗口来启动直接。
  • 使用的服务是不是默认的Windows服务 - 它被设计用于这种应用

 

感谢您的帮助的定制服务!

 

P.S.请注意,我对C#相当陌生,并且在我去这里学习。

 

UPDATE:

我设法得到报警邮件给每个服务启动时发送:当我继续通过我的代码阅读(我,不幸的是,不能发布这里),我注意到用于创建服务的类正在扩展ServiceBase类,并且有人使用自定义OnStart()方法来覆盖默认类。我添加了对新的OnStart()方法的必要方法调用,并成功发送了通知。

我试图为OnStop()方法做同样的事情,但对我来说这并没有那么好 - 在继续之前,我想补充一点,我已经用Java编程了好几年了,而且我非常熟悉Java设计模式。

我试图做的,这一点在Java工作过,是一个调用电子邮件通知重写ServiceBase类的OnStop()方法,投MyServiceServiceBase类型,然后再调用ServiceBase类的Stop()方法(注意:OnStop()是一种受保护的方法,因此无法直接调用 - Stop()方法调用OnStop(),然后继续使用必要的代码停止服务)。我认为铸造ServiceBase会强制调用默认的OnStop()方法,而不是我自定义的方法。

正如你可以想像,我结束了刚刚1万个电子邮件成功发送到我的收件箱之前,我设法在我的电脑强行进入硬关机。

我现在需要的是一种方法,既可以使用我重写OnStop()方法,然后把它调用默认的方法,或其他办法解决这个问题。任何和所有的帮助,非常感谢。非常感谢。

 

与多线程解决方案你所组成:

protected override void OnStart(string[] args) { 
    string subject = "Notice: Service Started"; 
    string body = "This message is to notify you that the service " + 
     "has been started. This message was generated automatically."; 
    EmailNotification em = new EmailNotification(subject, body); 
    em.SendNotification(); 

    ...INITIALIZE LISTENER FOR SERVICE STOPPING HERE... 

    ...custom stuff to be run on start... 
} 

而且,记住类调用此方法中,我们称之为Service,扩展了ServiceBase类。

 

更新两个:

的问候,我使用NotifyServerStatusChange据我了解,这是不允许的解决方案中使用的系统功能,由于各种原因的建议。澄清一下,只有纯粹在C#和.NET范围内的解决方案才是可行的。再次感谢你的帮助!

+0

看看wmi查询。 – Chriseyre2000 2012-07-30 19:39:53

+0

没错,但应用程序没有检查事件的状态 - 它需要持续监听状态变化 – 2012-07-30 19:41:56

+0

@ Chriseyre2000:这是一个有效的解决方案,迄今为止,我只有这个解决方案。如果你想删除评论并将其作为答案,我会对它进行投票,因为它是对此的唯一答案。然而,正如文章本身所说,代码会变得混乱,我真的不能朝这个方向前进。 – 2012-07-31 12:36:09

回答

2

这里是解决方案,为什么之前我无法找到它:正如我刚才所说,我的课扩展ServiceBase类。在我的第一次更新中,我发布了我试图解决这个问题的方式,我将用Java解决它:通过投射。但是,在C#中,如果在派生类中覆盖它,显然不会让您调用基本方法。当我第一次发布这个问题和这个更新(并且很明显是没有人想到的事情之一)时,我不知道的一件事是C#包括base构造函数,它可以用来从基类的方法调用派生类。由于base构造函数可用于C#中的任何类,因此它不会出现在ServiceBase Class documentation中。

一次我学到了这一点,我能够把我原来的解决方案并将其修改为使用基类:

protected override void OnStop() { 
     string subject = "Notice: Service Stopped"; 
     string body = "This message is to notify you that the service has " + 
      "been stopped. This message was generated automatically."; 
     EmailNotification em = new EmailNotification(subject, body); 
     em.SendNotification(); 
     base.OnStop(); 
    } 

我想通了这一点,当我在Visual Studio中,发现的代码打转转base在我的智能感知中。我点击进入其定义,并将它发送给ServiceBase(显然未定义)。在注意到我的代码中没有定义基础并且它是ServiceBase类的实例之后,我意识到它一定是某种构造函数。经过Google的快速搜索,我找到了我正在寻找的东西。去智能感知的方法!

谢谢大家对您的帮助!

1

ServiceController类有一个WaitForStatus方法。虽然它在内部进行轮询。

+0

是的,投票方面使它成为一个禁行,除非有人可以告诉我如何创建一个新的线程这个工作,如果没有它在性能方面花费我很多(注意:我一直在寻找多线程这个应用程序,但是,正如我之前所说,我对C#有点新,从我读过的内容来看,它听起来并不像它能够正确或高效地工作 - 思想?) – 2012-07-31 12:34:09

+0

您认为一个或几个轮询线程是性能问题?他们每250毫秒唤醒一次。你为什么认为这是一个不行? – usr 2012-07-31 13:01:55

+0

对不起,我不认为我的评论非常清楚 - 我不是说投票会是一个性能问题,只有第二个主题。在性能方面,投票本身对我来说完全没问题,但是当程序监听服务停止时,我需要做些事情。根据定义,轮询是忙等待的,除非我有两个线程,否则我不能这样做,这样我就可以在一个中等待,然后在另一个程序中通过其余的程序。 – 2012-07-31 13:09:48

1

如果你不能PInvoke的NotifyServiceStatusChange,那么你就必须轮询服务。例如:

ServiceController sc = new ServiceController("Some Service"); 
Console.WriteLine("Status = " + sc.Status); 
+0

这是一个很好的解决方案,如果我们要实现一个“心跳监视器”,它将很好的工作,但是我们的规范要求解决方案是服务本身的一部分,当服务被告知停止时,所以。 – 2012-07-31 14:41:39

0

使用NotifyServiceStatusChange()时要非常小心,因为它仅在Windows Vista/Windows 2008(及更高版本)上受支持。如果您针对以下任何平台,则无法使用该API。 (仍然有很多XP/Windows 2000-2003系统。)

更糟糕的是,如果服务重新启动,轮询将不会总是可靠的,因为如果您以非常快的速度轮询服务系统(SSD驱动器或虚拟机上的预缓冲I/O)时,服务可能会在两次轮询之间重新启动。

+0

谢谢 - 我经常检查堆栈,并且总是在我发布的帖子/问题上查看新答案/评论。你的帖子非常有见地,但它不仅仅是一种解决方案而是一种评论 - 你是否还有另一种解决方案可以提出建议? (如果没有,请将您的帖子更改为评论而不是答案)谢谢:) – 2013-07-02 16:33:58