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

时间:2014-05-21 19:02:58

标签: 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.
}

然而,在异常之后,Windows服务仍然作为一个进程保留,然后我必须在任务管理器中手动终止。

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

6 个答案:

答案 0 :(得分:27)

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

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

    // Do some work here if xml file exists.
    ...
}

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

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

答案 1 :(得分:7)

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

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

public bool Start(HostControl hc)
{
    hostControl = hc;
    Restart();
    return true;
}

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

hostControl.Stop();

答案 2 :(得分:5)

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

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

  

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

     

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

     

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

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

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

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

  

“您的应用程序除了在调用HostFactory.Run()方法之前配置NLog / Log4Net之外什么都不做。”

答案 3 :(得分:4)

我刚遇到这个问题,所有上述答案似乎都过于复杂。您需要做的就是使用接受WhenStarted的{​​{1}}重载,如果内部服务引导失败,则返回false。我不认为Func<T,HostControl,bool>需要明确调用。

hostControl.Stop()

答案 4 :(得分:2)

我已经&#34;借了&#34; 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
    });    

在上述代码运行之前,您必须检查文件系统。让我们来思考一下。提供服务的关键是确保RUNS和KEEPS RUNNING。您首先试图颠覆拥有服务应用程序的基本原则。而不是因为丢失文件而试图停止服务,而是找出一些方法来提醒您的支持人员,而不是根据丢失的文件做任何事情。

答案 5 :(得分:-3)

当您捕获异常时,可以使用ServiceBase.Stop()方法自行停止服务。

try
{
    // Your Code
}
catch (Exception ex)
{
    // The code for stopping service
}

在某些情况下,您还可以使用多个捕获块:

try
{
    // Your Code
}
catch (IndexOutOfRengeException ex)
{
    // The code for stopping service
}
catch (FileNotFoundException exc)
{
    // The code for stopping service
}

详细了解ServiceBase.Stop()