Using Custom Exception Handlers to Restart Your Application

When using the .NET Framework, you will implement try/catch blocks to handle specific exceptions that your application expects. However, one often-overlooked ability of .NET is that you can create a custom exception handler that will allow you to catch all unhandled exceptions thrown during the execution of your application. This allows you to terminate your application in a controlled manner and perform any needed application-specific cleanup and error logging.

This feature came in handy for me recently when a client requested that their application log any unhandled exceptions and automatically restart itself. In this week's installment to the C# Tips and Techniques series, I'll illustrate how .NET makes this a snap to implement.

  1. First, create a test C# Windows application (in the attached sample, I called mine RestartApp).
  2. Add the following using statement:
  3. using System.Threading;
  4. Add the following custom exception handling class. As you can see, it only contains two methods:
    • OnThreadException—This method logs the error exception, tells the user that the application will restart automatically, shuts down the current instance of the application, and then restarts the application. You'll see in the next step how this method is called automatically by the framework in response to any unhandled exceptions.
    • LogException—This very simple logging method (called from OnThreadException) logs the unhandled exception to a file whose name is generated from the current date and time.
    // Custom Exception class to catch all "unhandled exceptions"
    public class CustomExceptionHandler
    {
      // Event handler that will be called when an unhandled
      // exception is caught
      public void OnThreadException(object sender,
                                    ThreadExceptionEventArgs t)
      {
        // Log the exception to a file
        LogException(t.Exception);
    
        // Tell the user that the app will restart
        MessageBox.Show("A Fatal Error was detected and logged.
                         Click the OK button to restart the
                         application",
                         "Fatal Application Error",
                         MessageBoxButtons.OK, MessageBoxIcon.Stop);
    
        // Shut down the current app instance
        Application.Exit();
    
        // Restart the app
        System.Diagnostics.Process.Start(Application.ExecutablePath);
      }
    
      // *Very* simple logging function to write exception details
      // to disk
      protected void LogException(Exception e) 
      {
        DateTime now    = System.DateTime.Now;
        string error    = e.Message + "\n\nStack Trace:\n"
                                    + e.StackTrace;
        string filename = String.Format("Log-{0}{1}{2}-{3}{4}
                                        {5}.txt",
                                        now.Year.ToString(),
                                        now.Month.ToString(),
                                        now.Day.ToString(),
                                        now.Hour, now.Minute,
                                        now.Second);
    
        StreamWriter stream = null;
        try
        {
          stream = new StreamWriter(filename, false);
          stream.Write(error);
        }
        catch(Exception ex)
        {
          MessageBox.Show(ex.Message);
        }
        finally
        {
          if (null != stream)
            stream.Close();
        }
      }
    };
    
  5. Once the custom exception handling class is in place, plug it into the framework by inserting the following two lines of code into the Main method (before the call to Application.Run). The first line simply instantiates the class you defined in the previous step while the second line attaches the CustomExceptionHandler.OnThreadException method to the ThreadException event. That way, when an exception is thrown that is not explicity handled, the OnThreadException method is automatically called.
  6. CustomExceptionHandler eh    = new CustomExceptionHandler();
    Application.ThreadException += new System.Threading.
                                   ThreadExceptionEventHandler(eh.
                                      OnThreadException);
    
  7. Now, to test this, add two buttons to the form, as shown in Figure 2. As you can see, we're going to test that only unhandled exceptions cause the application to restart.
  8. Add a Click event handler for the "Handled Exception" button as follows:
  9. private void btnHandledException_Click(object sender,
                                           System.EventArgs e)
    {
      try
      {
        throw new Exception("Handled Exception");
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
      }
    }
    
  10. Add a Click event handler for the "Unhandled Exception" button as follows:
  11. private void btnUnhandledException_Click(object sender,
                                             System.EventArgs e)
    {
      throw new Exception("Unhandled Exception!!");
    }
    
  12. Run the application. When you click on the "Handled Exception" button, you should simply see a message box displaying the exception's text. However, clicking the "Unhandled Exception" button should result in the exception being logged and the application restarting itself, as shown back in Figure 1.


About the Author

Tom Archer - MSFT

I am a Program Manager and Content Strategist for the Microsoft MSDN Online team managing the Windows Vista and Visual C++ developer centers. Before being employed at Microsoft, I was awarded MVP status for the Visual C++ product. A 20+ year veteran of programming with various languages - C++, C, Assembler, RPG III/400, PL/I, etc. - I've also written many technical books (Inside C#, Extending MFC Applications with the .NET Framework, Visual C++.NET Bible, etc.) and 100+ online articles.

Comments

  • how i do for Restart my Application in the compact Framework

    Posted by alde007 on 04/07/2005 07:11pm

    i need restart my smart device application , bat the code: " // Shut down the current app instance Application.Exit(); // Restart the app System.Diagnostics.Process.Start(Application.ExecutablePath); i can`t use it

    Reply
  • Can this be extended to call app with original args?

    Posted by paulwoll on 05/15/2004 05:29pm

    Nice post. Is there a way to extend this so that the original calling arguments to application are used when it is restarted?

    • RE: Can this be extended to call app with original args?

      Posted by Tom Archer on 05/17/2004 11:08am

      Thanks. The System.Diagnostics.Process.Start method has a couple of overloads that allow you to pass params. One takes a string as the second param and the other takes a System.Diagnostics.ProcessStartInfo structure where you can specify multiple params. Just save the incoming params in a member variable (such as a string or an array) and then pass them to System.Diagnostics.Process.Start.

      Reply
    Reply
  • nice

    Posted by Sonu Kapoor on 05/03/2004 10:58am

    A very nice and neat function. sonu

    • Thanks!

      Posted by Tom Archer on 05/06/2004 12:30pm

      I'm glad it came in handy for you!

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Learn How A Global Entertainment Company Saw a 448% ROI Every business today uses software to manage systems, deliver products, and empower employees to do their jobs. But software inevitably breaks, and when it does, businesses lose money -- in the form of dissatisfied customers, missed SLAs or lost productivity. PagerDuty, an operations performance platform, solves this problem by helping operations engineers and developers more effectively manage and resolve incidents across a company's global operations. …

  • Live Event Date: December 18, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this upcoming webcast …

Most Popular Programming Stories

More for Developers

RSS Feeds