一个用.NET编写的服务可以自行终止吗?

21

我有一个用C#编写的服务应用程序,在某些情况下,我希望它能够自行终止。这将发生在服务运行一段时间后,因此不会在OnStart()事件中发生。

到目前为止,我所了解的信息表明,通过服务控制管理器是唯一安全的终止服务的方法。我的服务以本地服务运行,没有启动或停止服务的权限,因此无法从服务本身访问SCM。是否还有其他方式可以在遵守SCM规则的同时自我终止?

4个回答

36

1
我发现ServiceBase没有停止方法。我是从VS2010 IDE测试的。 - Thomas
1
该方法自 .Net 2.0 版本以来就存在,包括紧凑框架。请注意,它不是静态方法,您需要从扩展 ServiceBase 的类中调用它。 - configurator

9

如果你想终止服务而不是停止它(可能是因为服务捕获了一个未处理的异常),你可以使用Environment.Exit(1)(如果需要,可以使用其他退出代码)。

Windows将发现服务意外终止。如果已配置服务进行恢复,则将使用恢复过程,其中包括重新启动服务、运行程序或重新启动计算机的选项。


2
大多数情况下它都能正常工作。但在一些罕见的情况下(可能是某些终结器仍在运行或某些竞争条件),它会挂起。这时你就需要使用Environment.FailFast。因此,我找到的解决方案是 -ThreadPool.QueueUserWorkItem(ExitImmediate); Environment.Exit(1);其中ExitImmediate会休眠一段时间,然后执行FailFast。 - yu_sha
@yu_sha 感谢您的评论,我一直在思考如何强制结束我的服务。FailFast听起来很不错,但我绝对不想要它的转储(如果是完整的内存转储,它将达到100GB)。因此,我一直在尝试弄清楚Exit与Process.GetCurrentProcess().Kill()之间的区别,而您提到Exit可能会因任何原因而挂起,所以选择Kill! - Chris Marisic

5
如果您让所有正在执行的线程都完成,会发生什么?我可以想象三种可能的结果:
  • 服务控制管理器(SCM)会注意到并决定您已经适当地完成了
  • 服务控制管理器(SCM)会注意到并认为您已经死亡,并重新启动您
  • 服务控制管理器(SCM)没有注意到,并显示您仍在运行中
编辑:我怀疑这个答案是最好的,但出于兴趣的缘故,我将保留此内容。参考:这个答案

1
我相信第一个结果是正确的。但是你怎么做到的呢?主线程是由ServiceBase创建的消息循环(ServiceBase.Run(service)永远不会返回)。使Run()调用返回的方法是调用service.Stop() - 就像Application.Exit在Application.Run之后退出一样。 - configurator
我已经很久没有写Windows服务了,但我不记得它会为我运行消息循环。嗯,可能只是我的记忆不好... - Jon Skeet
2
这不是消息循环。服务控制管理器将主线程置于等待状态,并唤醒它以调用控制处理程序回调。当进程中的所有服务都停止时,它将被释放,ServiceBase.Run方法将返回。 - Stephen Martin
那和消息循环有什么区别? Windows Forms进程会等待回调,而Windows服务则会一直等待回调。除了术语上的差异之外,还有其他区别吗? - configurator
消息循环是 Windows 编程中一个明确定义的术语,它涉及到一个活跃地从消息队列中移除项目、处理它们并请求另一个的线程。而 SCM 对进程的主线程所做的工作在质上是不同的。 - Stephen Martin
显示剩余3条评论

-2

不要让服务在本地服务下运行。请让它在一个有停止服务权限的用户下运行。

虽然自我终止服务的想法并不是最好的想法。但这个事实本身就意味着它应该是一个应用程序,而不是一个服务。


1
我不同意 - 我可以想象一个某种类型的服务器(例如一个 Web 服务,但不在 IIS 下运行),它有一个包括“停止”的管理员面板。 - Jon Skeet
@Jon:你的示例中的管理面板不应该作为自己的应用程序运行吗?一个有权停止和启动服务的应用程序? - configurator
我在这方面支持Jon。管理员面板可能不在同一台机器上;甚至可能不在Windows上。 - jdigital
@Jon:可能是这样(有这样的产品),但在那种情况下,这取决于用户运行管理面板的功能,他们应该向SCM发送停止服务的信号,而不是让服务本身停止自己。 - casperOne
@jddigital: 看一下我对Jon评论的回应。此外,这可能是一个安全问题,因为你可以给那些拥有服务访问权限的人关闭它的权利,而他们通常没有这样的权限。 - casperOne

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