如何捕获异常并停止Topshelf服务?

JD.*_*JD. 17 c# topshelf

我有一个topshelf Windows服务,我想做一些检查(即如果存在xml文件),如果检查失败,我需要Windows服务停止.

所以我尝试在Start()方法中进行检查,然后引发异常:

public void Start()
{
    if (!File.Exists(_xmlFile) throw new FileNotFoundException();
    // Do some work here if xml file exists.
}
Run Code Online (Sandbox Code Playgroud)

但是,Windows服务作为异常之后的进程保留,然后我必须在任务管理器中手动终止.

如果某些条件(即未找到文件)成立,是否有办法不运行服务?

jul*_*o.g 28

您可以使用HostControl对象并修改您的方法,如下所示:

public bool Start(HostControl hostControl)
{
    if (!File.Exists(_xmlFile) 
    {
        hostControl.Stop();
        return true;
    }

    // Do some work here if xml file exists.
    ...
}
Run Code Online (Sandbox Code Playgroud)

你需要将HostControl传递给Start方法,如下所示:

HostFactory.Run(conf =>
{
    conf.Service<YourService>(svcConf =>
    {
        svcConf.WhenStarted((service, hostControl) =>
        {
            return service.Start(hostControl);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议在失败的情况下返回“ false”-这似乎会使TopShelf向服务控制管理器报告服务无法启动。 (2认同)

101*_*01V 8

每个WhenXxx方法也可以采用HostControl接口的参数,该参数可用于请求停止服务,请求额外的启动/停止时间等.

在这种情况下,将start()的签名更改为bool start(HostControl hc).在服务中保留对此HostControl的引用,如下所示:

public bool Start(HostControl hc)
{
    hostControl = hc;
    Restart();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

现在,当您想要停止服务时,请使用以下调用:

hostControl.Stop();
Run Code Online (Sandbox Code Playgroud)


Jas*_*tti 5

我从Topshelf文档中的最佳实践或建议的角度对此感到好奇,但找不到任何东西.然而,我确实从phatboyg找到了两个单独的评论...

最佳评论...如何通过此问题停止服务异常(我删除了一些细节):

如果服务的Start方法抛出异常,则服务将无法启动.

服务运行后,如果抛出未处理的异常,服务将停止,并将其作为崩溃报告给服务控制管理器.

如果需要以编程方式停止服务,请使用HostControl方法Stop.

所以我认为最简单的答案是抛出异常.

你正在这样做,你提到"Windows服务在异常后作为一个进程停留".这似乎是代码中某处不相关的错误,或者您可能以某种方式运行了多个实例?我今天早上一直在测试这些场景,并且在start方法中抛出异常后没有看到我的服务正在运行.

此外,与在接受的答案中提到的HostFactory.Run之前的检查相关,通过https://groups.google.com/forum/embed/#!topic/topshelf-discuss/nX97k3yOhJU:

"在调用HostFactory.Run()方法之前,您的应用程序应该只执行配置NLog/Log4Net."

  • 我已经尝试过这个......在停止服务的启动方法中抛出异常......但它不会在执行过程中停止服务。正如@julio 所解释的,我不得不使用 hostControl.Stop() 来停止服务 (2认同)

Xav*_*r J 3

我“借用”了 topshelf 功能设置的示例代码来演示一点:

HostFactory.Run(x =>                                 //1
    {
        x.Service<TownCrier>(s =>                        //2
        {
           s.ConstructUsing(name=> new TownCrier());     //3
           s.WhenStarted(tc => tc.Start());              //4
           s.WhenStopped(tc => tc.Stop());               //5
        });
        x.RunAsLocalSystem();                            //6

        x.SetDescription("Sample Topshelf Host");        //7
        x.SetDisplayName("Stuff");                       //8
        x.SetServiceName("stuff");                       //9
    });    
Run Code Online (Sandbox Code Playgroud)

您必须在运行上述代码之前检查文件系统。让我们考虑一下。拥有服务的重点是确保它运行并保持运行。您首先试图颠覆服务应用程序的基本原则。不要因为丢失文件而尝试停止服务,而是想出某种方法来提醒您的支持人员,而不是做任何依赖于丢失文件的事情。

  • 我不同意这一点。您可能需要一些先决条件来检查,如果不满足,则运行该服务是没有意义的。 (11认同)
  • 经典的 Stack Overflow 内容。“我希望我的服务自行停止”“你不应该这样做,因为你正在颠覆一个基本原则”。天哪,我是程序员,让我选择是否停止它。感谢 julio.g 在下面的一些理智。 (10认同)
  • Topshelf 确实提供了一种以这种方式关闭的方法。请参阅下面@julio.g 的回答 (3认同)
  • 我有点好奇 Topshelf 的作者对这个场景有何看法。我没有找到任何东西来回答这个问题,但确实看到了这个评论[这里](https://groups.google.com/forum/embed/#!topic/topshelf-discuss/nX97k3yOhJU):“你的应用程序应该做无非是在调用 HostFactory.Run() 方法之前配置 NLog/Log4Net 。” (2认同)