I have a topshelf windows service where I want to do some checking (i.e. if an xml file exists) and if the check fails I need the windows service to stop.
So I tried doing the check in the Start() method and then raise an exception:
public void Start()
{
if (!File.Exists(_xmlFile) throw new FileNotFoundException();
// Do some work here if xml file exists.
}
However, the windows service stays around as a process after the exception which I then have to kill manually in the task manager.
Is there a way to not run the service if certain conditions (i.e. file not found) hold?
I just ran into this issue and all the above answers seem to be over complicating things. All you need to do is use the
WhenStarted
overload that accepts aFunc<T,HostControl,bool>
and return false if your internal service bootstrap failed. I don't thinkhostControl.Stop()
needs to be called explicitly.I've "borrowed" the sample code for the functional setup of topshelf to demonstrate a point:
You're going to have to place your file system check BEFORE the above code runs. Let's think about this a second. The point of having a service is to make sure it RUNS and KEEPS RUNNING. You're attempting to subvert a basic principle of having service applications in the first place. Instead of trying to stop the service because of the missing file, figure out some way to alert your support staff and NOT do whatever depends on that missing file.
I was curious about this from the point of view of a best practice or recommendation in Topshelf's documentation, but couldn't find anything. I did, however, find two separate comments from phatboyg...
Best comment... how to stop service on exception, via this issue (I cut out some of the detail):
So I think the easiest answer is to throw an exception.
You were doing that, and you mention "the windows service stays around as a process after the exception". That seems like an unrelated bug somewhere in your code, or perhaps you somehow had multple instances running? I've been testing these scenarios this morning and have not seen my service running after throwing an Exception in the start method.
Also, relevant to checking before HostFactory.Run, mentioned in the accepted answer, via https://groups.google.com/forum/embed/#!topic/topshelf-discuss/nX97k3yOhJU:
You could use the HostControl object and modify your method like this:
And you will need to pass the HostControl in to the Start method like this:
Each of the WhenXxx methods can also take an argument of the HostControl interface, which can be used to request the service be stopped, request additional start/stop time, etc.
In such case, change signature of start() to be bool start(HostControl hc). Retain reference to this HostControl in the service as follow:
Now when you want to stop the service use following call:
When you catch the exception you can use
ServiceBase.Stop()
Method to stop the service by itself.Also you can have multi catch blocks in some cases:
Read more about ServiceBase.Stop()