views:

404

answers:

6

I am writing a windows service that needs to be running 24/7. It is a pretty simple service that monitors a directory where files are dropped into and processes those files. I need to restart the service if an unhandled exception is thrown.

Is there a way for a service to restart itself in the event of an unhandled exception?

+2  A: 

Have you tried using the Recovery tab of the Service entry - you can set rules for failures, including "Restart the Service" - by default this is on "No Action"

JustinD
I didnt realize that this was even available. Thanks!
Aaron M
I would be wary of doing this. If there is a serious exception that is thrown every time the service starts, what then? How will you know?
Dan Diplo
I'm not saying it's a good idea - I'm saying it can be done...To that point, the real question is why you would plan on having unhandled exceptions rather than catching them and, if it is that critical, stopping the service from within the code.
JustinD
You can setup the service to count the number of failures, and for the First second and third failure you can specify different actions. you can also append a fail count to the command line, and reset the fail count after so many days.
Aaron M
Two questions with this restart thing: 1. Is it available pre-Vista? I seem to remember that it was added just then. 2. You say to do it using the recovery tab. Can this be done from the service itself, or at the very least from the installer? If so, how?
OregonGhost
A: 

Wrap your service code in a runner which can catch any errors and restart your service.

theGecko
A: 

The best way is to wrap Try / Catch blocks around the methods in the service you can afford to let throw exceptions.

However, there may be serious exceptions thrown that should result in the service being stopped immediately. Don't ignore these! In these cases, handle the exception, log it, email it and then rethrow it. That way you will be informed that the exception has occurred and will know what went wrong. You can then fix the problem and re-start the service manually.

Just ignoring it could cause a major failure in your system which you would not know about. It could also be very expensive on CPU/RAM if the service stops then restarts then stops ad infinitum.

Dan Diplo
+2  A: 
John Saunders
+1  A: 

This is able to be done programatically if you wanted, this code was not written by me. I am posting the link to the Authors CodeProject page that contains the source / binaries. Below the link I have explained how I implemented the authors code.

http://www.codeproject.com/KB/install/sercviceinstallerext.aspx

  1. Add a reference to the DLL.

  2. Open ProjectInstaller.Designer.vb in notepad
    In the InitializeComponent Sub
    CHANGE
    Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
    Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller
    TO
    Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
    Me.ServiceInstaller1 = New Verifide.ServiceUtils.ServiceInstallerEx

  3. With the Friend Declarations in the ProjectInstaller.Designer.vb
    CHANGE
    Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
    Friend WithEvents ServiceInstaller1 As System.ServiceProcess.ServiceInstaller
    TO
    Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
    Friend WithEvents ServiceInstaller1 As Verifide.ServiceUtils.ServiceInstallerEx

  4. CHANGE
    Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
    TO
    Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceInstaller1, Me.ServiceProcessInstaller1})

  5. Import The Namespace On ProjectInstaller.vb

  6. In ProjectInstaller.vb in the Public Sub New Function After Initialize component function has been called
    ADD
    'Set Reset Time Count - This Is 4 Days Before Count Is Reset
    ServiceInstaller1.FailCountResetTime = 60 * 60 * 24 * 4
    'ServiceInstaller1.FailRebootMsg = "Houston! We have a problem"

    'Add Failure Actions
    ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
    ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
    ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.None, 3000))

    ServiceInstaller1.StartOnInstall = True

  7. Build installer and install. Voila

Zman101
A: 

Hi Aaron.

As suggested by "John Saunders" and "theGecko", you can monitor the service and restart it when it fails. The builtin Windows Service Recovery functionality will get you a long way, but if you find that you need some more advanced features (for example, CPU hogging and hang detection) then please check out Service Protector. It is designed to keep your important Windows Services operating 24x7.

Good luck!

CoreTech