如何捕获exception并停止Topshelf服务?

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

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

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

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

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

我已经“借用”了topshelffunction设置的示例代码来演示一个观点:

 HostFactory.Run(x => //1 { x.Service(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。 您试图首先颠覆拥有服务应用程序的基本原则。 而不是因为丢失文件而试图停止服务,而是找出一些方法来提醒您的支持人员,而不是根据丢失的文件做任何事情。

您可以使用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(svcConf => { svcConf.WhenStarted((service, hostControl) => { return service.Start(hostControl); } } } 

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

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

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

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

 hostControl.Stop(); 

我刚刚遇到这个问题,所有上述答案似乎都过于复杂。 您需要做的就是使用接受FuncWhenStarted重载,如果内部服务引导失败,则返回false。 我不认为hostControl.Stop()需要显式调用。

 //Here is bit from inside the .Service() call s.WhenStarted((YourService svc, HostControl hc) => svc.Start()); //And the svc.Start method would look something like this: class YourService { public bool Start() { //return true if all is well //or false if you want service startup to be halted } } 

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

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

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

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

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

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

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

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

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

捕获exception时,可以使用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()的更多信息