When an application crashes, users do not want to lose the data they were working on. Ideally, the application should restart automatically and restore their context. This is exactly what the Application Recovery and Restart (ARR) API provides. Application Recovery and Restart lets you define a callback to invoke when the application crashes so you can save the current state, and it also controls whether the application restarts automatically.
Let's start with some imports:
C#
public delegate int RecoveryDelegate(IntPtr parameterData);
[DllImport("kernel32.dll")]
public static extern int RegisterApplicationRecoveryCallback(RecoveryDelegate recoveryCallback, IntPtr parameter, uint pingInterval, uint flags);
[DllImport("kernel32.dll")]
public static extern int ApplicationRecoveryInProgress(out bool canceled);
[DllImport("kernel32.dll")]
public static extern void ApplicationRecoveryFinished(bool success);
[DllImport("kernel32.dll")]
public static extern int UnregisterApplicationRecoveryCallback();
[DllImport("kernel32.dll")]
public static extern int RegisterApplicationRestart([MarshalAs(UnmanagedType.LPWStr)] string commandLineArgs, RestartRestrictions flags);
[DllImport("kernel32.dll")]
public static extern int UnregisterApplicationRestart();
[Flags]
public enum RestartRestrictions
{
None = 0,
NotOnCrash = 1,
NotOnHang = 2,
NotOnPatch = 4,
NotOnReboot = 8,
}
To indicate that the application must restart automatically, add the following lines:
C#
static void Main(string[] args)
{
RecoveryAndRestart();
if (args.Contains("/restart"))
{
// TODO restore the context
}
// TODO the code of your app
}
static void RecoveryAndRestart()
{
if (Environment.OSVersion.Version.Major >= 6) // Windows Vista and above
{
RegisterApplicationRestart("/restart", RestartRestrictions.None);
}
}
The feature is available only on Windows Vista and later, hence the OS version check. "/restart" is the command-line argument passed when restarting the application, which lets you determine whether the application is starting normally or recovering from a crash. The second argument specifies when the application is allowed to restart automatically. RestartRestrictions.None indicates that the application should restart in all cases.
Saving the application state is slightly more involved, but still straightforward. The first step is to register the recovery callback:
C#
static void Main(string[] args)
{
RecoveryAndRestart();
}
private static void RecoveryAndRestart()
{
if (Environment.OSVersion.Version.Major >= 6)
{
RegisterApplicationRecoveryCallback(ApplicationRecoveryCallback, IntPtr.Zero, pingInterval: 5000, flags: 0);
RegisterApplicationRestart("/restart", RestartRestrictions.None);
}
}
Use the callback to save any user data that can be restored when the application restarts. You should also periodically signal that recovery is still in progress by calling ApplicationRecoveryInProgress, and check whether the user has requested cancellation. Finally, call ApplicationRecoveryFinished to signal that the application is ready to restart. The callback looks like:
C#
private int ApplicationRecoveryCallback(IntPtr parameterData)
{
try
{
// Notifies WER (Windows Error Reporting) regularly that the application is working.
// The interval must be smaller than the value of "pingInterval" set during
// the call to RegisterApplicationRecoveryCallback, otherwise WER will consider
// the application as unresponsive and terminate it
var pinger = new System.Timers.Timer(4000);
pinger.Elapsed += (sender, args) =>
{
bool isCanceled;
ApplicationRecoveryInProgress(out isCanceled);
if (isCanceled)
{
Environment.Exit(2);
}
};
pinger.Enabled = true;
// TODO Save the state of the application
File.WriteAllText("data.txt", "data");
}
finally
{
ApplicationRecoveryFinished(true);
}
return 0;
}
When a crash occurs, the following window is displayed:

Then the application restarts automatically:

Do you have a question or a suggestion about this post? Contact me!