tags:

views:

336

answers:

4

How can I detect that my .NET application has crashed, and then restart it?

A: 

A possible solution is to create another process to monitor your application, and restart it if it is terminated:

class ProcessMonitorProgram
{
    const string myProcess = "MyApp.exe";

    static void Main()
    {
        new Timer(CheckProcess, null, 0, 60 * 1000);
        Thread.Sleep(Timeout.Infinite);
    }

    static void CheckProcess(object obj)
    {
        if (Process.GetProcessesByName(myProcess).Length == 0)
            Process.Start(myProcess);
    }
}

One of the problems with this solution is that it will keep the process restarting forever, until this monitoring application itself is terminated.

Hosam Aly
+5  A: 

Another solution (based on this example) is to create a launcher that controls the application:

class LauncherProgram
{
    static int count = 3;

    static void Main()
    {
        Launch();
        Thread.Sleep(Timeout.Infinite);
    }

    static void Launch()
    {
        Process process = new Process();
        process.StartInfo.FileName = "MyApp.exe";
        process.EnableRaisingEvents = true;
        process.Exited += LaunchIfCrashed;
    }

    static void LaunchIfCrashed(object o, EventArgs e)
    {
        Process process = (Process) o;
        if (process.ExitCode != 0)
        {
            if (count-- > 0) // restart at max count times
                Launch();
            else
                Environment.Exit(process.ExitCode);
        }
        else
        {
            Environment.Exit(0);
        }
    }
Hosam Aly
The only possible upgrade would be to make the "watchdog" a windows service.
Ryan Emerle
+5  A: 
  • run the work inside an AppDomain; use the primary AppDomain to monitor it (doesn't guard against process kill, though)
  • lots of exception handling! i.e. don't let a fatal error tear down the process
  • run it in something that already has recycling built in - IIS for example
Marc Gravell
Thanks Marc. Could you please add an example on how to implement the AppDomain-based solution you suggest?
Hosam Aly
Assuming this is a Windows Forms or console app, you can use Application.Restart - see my answer for details.
RoadWarrior
+3  A: 

If this is a Windows Forms app:

  • Set jitDebugging = true in App.Config. This prevents the built-in Windows Forms unhandled exception handler being triggered.

Now regardless of whether this is a Windows Forms app or a console app:

  • Register for the Application.ThreadException event, e.g. in C#:

    Application.ThreadException += new Threading.ThreadExceptionHandler(CatchFatalException);

At this point, your app is already on its way into a black hole. What happens next depends on whether or not this is a Windows Forms app:

  • If it's a Windows Forms app, call the Application.Restart method in your CatchFatalException event handler.
  • Otherwise you will instead need to p/invoke to the application restart and recovery native functions. That link discusses Vista, but in my tests it works just fine on XP as well.
RoadWarrior
Thank you. Is it possible for a console application to do something similar to `Application.ThreadException += MyHandler;`?
Hosam Aly
Yes, a console app can do the same.
RoadWarrior
But it does not have access to the Application class, does it?
Hosam Aly
It does have access to the Application class if you add the correct namespace. But in my test, I see an "Unsupported" exception, so you're right, this doesn't work for Console apps. I will change my answer to reflect this.
RoadWarrior