December 19, 2014
Hot Topics:

C++ Tip: Using Custom Exception Handlers to Restart Your Application

  • May 3, 2004
  • By Tom Archer
  • Send Email »
  • More Articles »

Welcome to this week's installment of .NET Tips & Techniques! Each week, award-winning Architect and Lead Programmer Tom Archer demonstrates how to perform a practical .NET programming task using either C# or Managed C++ Extensions.

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 1. 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 in Figure 2.

Download the Code

To download the accompanying source code for this tip, click here.

About the Author

The founder of the Archer Consulting Group (ACG), Tom Archer has been the project lead on three award-winning applications and is a best-selling author of 10 programming books as well as countless magazine and online articles.




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel