Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Vista Application Crash Recovery in C#

4.79/5 (18 votes)
4 Mar 20072 min read 1   1.2K  
A demonstration class for adding Application Recovery to your Windows Vista C# application.

Sample Image - VistaApplicationRecovery.jpg

Introduction

Using the new Vista API, your application can now attempt to recover from a crash.

Background

A new feature available in Vista is the ability to have a callback when your application crashes. This can allow you to attempt to persist your applications data before it is terminated. Upon restart, you can then reload that persisted data, thus giving your user a better experience (of course, it shouldn't crash in the first place, but we're being realistic, right!).

Using the code

I've created a class called ApplicationRecovery. You can use this in your own applications to be notified when there is a crash and attempt to persist the data.

The main areas you should make note of are:

  • The Main() function in Program.cs needs modifying:

    C#
    static void Main()
    {
      //Turn off global exception handling.
      Application.SetUnhandledExceptionMode(
         UnhandledExceptionMode.ThrowException);
    
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
    
      using (Form1 form = new Form1())
      {
        //Add the event handler
        ApplicationRecovery.OnApplicationCrash +=
            new ApplicationRecovery.ApplicationCrashHandler(
                form.ApplicationRecovery_OnApplicationCrash);
    
        //Let Windows Vista know that your
        //application wants notification when it crashes.
        ApplicationRecovery.RegisterForRestart();
    
        Application.Run(form);
      }
    }

  • In the Form1() constructor (or another appropriate place) you need to check if there is recovery data that the application should attempt to load.

    C#
    public Form1()
    {
      InitializeComponent();
    
      //Check to see if the recovery file exists.
      //If it does, attempt to recover the data.
      if (System.IO.File.Exists(Application.UserAppDataPath +
        @"\" + RECOVERY_FILENAME))
      {
        if (RecoverData())
        {
          //Change the form title
          this.Text += "- Recovered";
        }
        else
        {
          //Change the form title
          this.Text += "- Could not recover";
        }
      }
    
      tmrCrashCountdown.Start();
    }

  • In the sample application there is a timer tmrCrashCountdown which prevents the user from crashing the application before 60 seconds. The application needs to be running for at least 60 seconds before Windows will attempt to recover and restart. This is so that you don't get an application continually crashing and restarting.

  • Finally, you need to implement the handler for the ApplicationRecovery.OnApplicationCrash event and the RecoverData() method. This is referenced in the Main() function.

    C#
    public void ApplicationRecovery_OnApplicationCrash()
    {
      try
      {
        //Save the data to recover to a text file.
        //You may use any method you deem fit.
        System.IO.File.WriteAllText(Application.UserAppDataPath +
            @"\" + RECOVERY_FILENAME, DataToRecover);
    
        //Let the application recovery know that you
        //finished successfully.
        ApplicationRecovery.ApplicationRecoveryFinished(true);
      }
      catch
      {
        //Or let it know that recovery failed.
        ApplicationRecovery.ApplicationRecoveryFinished(false);
      }
    }
    
    private bool RecoverData()
    {
      bool result;
    
      try
      {
        txtData.Text = System.IO.File.ReadAllText(
            Application.UserAppDataPath + @"\" + RECOVERY_FILENAME);
        System.IO.File.Delete(Application.UserAppDataPath +
            @"\" + RECOVERY_FILENAME);
        result = true;
      }
      catch
      {
        result = false;
      }
    
      return result;
    }

Our application saves the data to a text file, and reloads it on restart. You can implement any method you prefer to persist your data.

A quick look at the ApplicationRecovery class

The ApplicationRecovery class imports the following four functions from the new Vista API:

  • RegisterApplicationRestart
  • RegisterApplicationRecoveryCallback
  • ApplicationRecoveryInProgress
  • ApplicationRecoveryFinished

RegisterApplicationRestart notifies windows that we would like the application to be automatically restarted in the event of a crash.

The RegisterApplicationRecoveryCallback function is the one which is called by Vista when it notifies your application that it is going to be shutdown.
The callback function itself calls our function HandleApplicationCrash which raises our OnApplicationCrash event.

If the user clicks cancel whilst waiting for us to recover, we get notified by the output parameter of ApplicationRecoveryInProgress (which we check every second thanks to a timer in our callback function). When we have finished, we let Windows know by using the ApplicationRecoveryFinished passing either true of false (depending upon our success at recovery).

Points of Interest

The method for debugging the recovery code is worth noting.

  1. Remember to run the application outside of the Visual Studio debugger (Start Without Debugging).
  2. When it crashes, and before you click on either the "Send To Microsoft" or "Cancel" button in the Error Reporting dialog you should use Debug > Attach To Process and attach to your process. Your code will now jump into callback function (HandleApplicationCrash).

History

  • 4th March 07 - Modified ResgtartFlags enum definitions in source code to match updated MSDN documentation (thanks georg)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here