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:
static void Main()
{
Application.SetUnhandledExceptionMode(
UnhandledExceptionMode.ThrowException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
using (Form1 form = new Form1())
{
ApplicationRecovery.OnApplicationCrash +=
new ApplicationRecovery.ApplicationCrashHandler(
form.ApplicationRecovery_OnApplicationCrash);
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.
public Form1()
{
InitializeComponent();
if (System.IO.File.Exists(Application.UserAppDataPath +
@"\" + RECOVERY_FILENAME))
{
if (RecoverData())
{
this.Text += "- Recovered";
}
else
{
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.
public void ApplicationRecovery_OnApplicationCrash()
{
try
{
System.IO.File.WriteAllText(Application.UserAppDataPath +
@"\" + RECOVERY_FILENAME, DataToRecover);
ApplicationRecovery.ApplicationRecoveryFinished(true);
}
catch
{
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.
- Remember to run the application outside of the Visual Studio debugger (Start Without Debugging).
- 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)
Chris Buckett is developer based in Maidstone, Kent, UK. He has been producing beskpoke software solutions in the accounting and technology fields since 1995, initially using Borland Delphi, and in the past few years using Microsoft C#, VB.Net, ASP.NET, Winforms, Sql Server and related technologies.
Chris Buckett is married with 2 children, and enjoys hiking, photography and playing the melodeon (although rarely all at the same time).