运行进程作为Windows服务的最佳实践是什么?

25

在将您的进程或可执行文件作为服务运行时,有没有需要注意的事项?例如,如何进行无声日志记录和处理关键错误报告场景等方面?您是如何处理这些问题的?


1
微软有一篇KB文章,链接为https://support.microsoft.com/en-us/kb/821794。 - kiran
6个回答

23

针对严重错误报告,你只能使用标准的服务设置(通过已安装服务的属性)或自己动手做些什么。这可以是一个简单的日志文件,记录意外错误(通过使用AppDomain.UnhandledException来捕获和记录它们),使用Windows事件日志记录类似的信息,或者让另一个进程监视服务的错误(即服务停止)并警报某个人。

微软有一篇文章,名为“Windows服务应用程序介绍”,是关于在.Net中制作服务的很好的概述。

从我的经验中了解到开发Windows服务的其他事情:

  • Windows服务允许大约30秒启动。之后,Windows会将其报告为未正确启动。这意味着您需要确保服务的OnStart方法启动一个新线程运行服务,然后返回。
  • 不要期望任何用户交互(例如消息框,确认)因为服务是无界面的运行,“无头”的(即没有用户界面),所以您不能指望用户与其交互。
  • 检查服务将要运行的帐户,以确保您不会像一个权限过高的用户运行它。
  • 广泛使用日志记录(例如log4net),以便您可以在运行时查看服务正在做什么,并能够诊断任何错误(通过记录堆栈跟踪)。
  • 确保使用正确的InstallUtil版本(即32位或64位)安装服务。更好的方法是让服务使用ManagedInstallerClass.InstallHelper自己安装。

2
所以我们真的需要一个“合并答案”的功能,这样我们两个都可以是正确的 :). 特别是对于这些主观的“列表”类型问题。 - TheSoftwareJedi
+1 是的,就像 EE 上可以有“协助解决方案”一样。 - James
1
这是MSDN页面上的引用:“此API支持.NET Framework基础结构,不建议直接从您的代码中使用。”那么我应该让服务自行安装吗? - BanksySan
@BanksySan,请查看我在这个答案上的评论。 - adrianbanks

15
  • 一定要使用跟踪/日志API获取诊断信息。事件日志、日志文件、数据库等等... 把故障排除信息放在某个地方。
  • 尽早、经常进行跟踪/记录。没有什么比不得不进行代码更改才能添加诊断跟踪更令人沮丧的了。
  • 注意内存泄漏问题。当编写一个每天都会重新启动或作为计划任务运行的应用程序时,有时候我们会变得有点懒惰。请记住,这个服务需要彻底清理自己。请正确使用所有IDisposable对象的using子句。
  • 别忘了在你的STOP变量上使用volatile关键字!我的天啊,这每次都让我犯迷糊。

1
STOP变量是什么?听起来像是我应该注意的东西。 - BanksySan
1
@BanksySan 通常情况下,Windows服务代码会在循环中检查一个布尔实例变量以获取停止信号。while (!stop) { //服务代码 }... 这个stop变量必须被标记为volatile。 - TheSoftwareJedi

3

我有一个好方法,在你的OnStart方法或更好的是在Main方法之前添加以下代码。

#if DEBUG
   //LogMessage("Service starting");
   #warning The service has been set to break on debug. Only used for debugging.

   //LogMessage("DEBUG MODE - If the service crashed after this then your problem is that you're running in DEBUG mode without a Visual Studio installed.");
   if (Debugger.IsAttached == false) Debugger.Launch();
#endif

基本上,重要的部分是 Debugger.Launch(),它会在启动服务时弹出一个窗口,询问您是否想要调试服务以及使用哪个Visual Studio进行调试。这使得与服务一起工作变得更加方便和出色。我把#warning放在那里只是为了让它显示在警告列表中,以提醒我它的存在,尽管#if DEBUG应该可以防止大多数问题。

只需记住不要在部署时运行此代码(即不要发布调试代码),因为如果机器上没有安装Visual Studio,它会崩溃。


同时,在处理服务时,我创建了一个工具,帮助我极大地提高了效率,加速了它们的启动和关闭 - https://bitbucket.org/mmihajlovic/servicemanager - Mladen Mihajlovic

3

不要显示任何消息框/对话框。

请注意,您的应用程序通常不会在与登录用户相同的帐户下运行。因此,如果用户能够访问某个文件/目录,这并不意味着服务也可以这样做。


3

确认您拥有某种警报系统,以便在服务崩溃时通知您,例如向自己或某个邮箱发送电子邮件。


1
如果有意义的话,不要忘记实现暂停事件。 处理所有异常,以便在失败时优雅地失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接