【问题标题】:Can a service written in .NET self-terminate?用 .NET 编写的服务可以自行终止吗?
【发布时间】:2009-02-16 19:24:29
【问题描述】:

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

到目前为止,我所阅读的所有内容都表明,终止服务的唯一安全方法是通过服务控制管理器。我的服务作为本地服务运行,并且没有启动或停止服务的权限,因此我无法从服务本身访问 SCM。是否有另一种方法可以在仍然按照 SCM 规则玩的同时自行终止?

【问题讨论】:

    标签: c# windows-services


    【解决方案1】:

    【讨论】:

    • 我看到 ServiceBase 没有停止方法。我从 VS2010 IDE 测试它。
    • 该方法从.Net 2.0开始就存在,包括紧凑的框架。请注意,它不是静态方法,您需要从扩展 ServiceBase 的类中调用它。
    【解决方案2】:

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

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

    【讨论】:

    • 大部分时间它都有效。在极少数情况下(可能某些终结器仍在运行或某些竞争条件)它会挂起。然后你必须使用 Environment.FailFast。所以,我找到的解决方案是 - ThreadPool.QueueUserWorkItem(ExitImmediate); Environment.Exit(1); 其中 ExitImmediate 休眠了一段时间,然后执行 FailFast。
    • @yu_sha 感谢您的评论,我一直在讨论如何强制结束我的服务。 FailFast 听起来很棒,但我绝对不想要它的转储(如果它是完整的内存转储,它将是 100GB)。所以我一直在试图弄清楚 Exit vs Process.GetCurrentProcess().Kill() 并且你提到 exit 可以出于任何原因挂起,杀死它!
    【解决方案3】:

    如果你只是让所有正在执行的线程完成会发生什么?我可以想象三种可能的结果:

    • SCM 通知并决定您已正确完成
    • SCM 注意到,认为你死了,然后重启你
    • SCM 没有注意到,并显示您仍在运行

    编辑:我怀疑this answer 确实是最好的,但为了感兴趣,我将(暂时)保留它。

    【讨论】:

    • 我相信第一个结果是正确的。但是你如何做到这一点?主线程是由 ServiceBase 创建的消息循环,(ServiceBase.Run(service) 永远不会返回)。导致 Run() 调用返回的方法是调用 service.Stop() - 就像 Application.Exit 在 Application.Run 之后退出一样。
    • 我已经很久没有写 Windows 服务了,但我不记得它为我运行了一个消息循环。唔。一定是我记性不好……
    • 当然,我可能是错的。我写的服务不多……不过我会研究一下。
    • 这不是消息循环。服务控制管理器将主线程置于等待状态并唤醒它以调用控制处理程序回调。当进程中的所有服务都停止后,它被释放,ServiceBase.Run 方法返回。
    • 这和消息循环有什么区别? Windows 窗体进程等待回调,而 Windows 服务等待回调。除了术语有什么不同吗?
    【解决方案4】:

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

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

    【讨论】:

    • 我不同意 - 我可以想象一个带有包含“停止”的管理面板的某种描述的服务器(如 Web 服务,但不在 IIS 下运行)。
    • @Jon:您的示例中的管理面板不应该作为自己的应用程序运行,一个有权停止和启动服务的应用程序吗?
    • 我同意 Jon 的观点。管理面板可能不在同一台机器上;它甚至可能不在 Windows 上。
    • @Jon:可能是这种情况(有些产品会这样做),但在这种情况下,这是用户运行管理面板的功能,他们应该将信号发送到SCM 来停止服务,而不是让服务本身来停止自己。
    • @jddigital:请参阅我对 Jon 评论的回复。此外,这可能是一个安全问题,因为您可以让有权访问该服务的人有权将其关闭,而他们通常无权这样做。
    猜你喜欢
    • 2012-07-30
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多