Background
Application Recovery and Restart (ARR) is a feature that allows you to prepare for the impossible (?) case where your application crashes or waits forever (“Not Responding”).
The feature lets you “register” for these cases in order to give you the opportunity to save the application data or do some clean up operations, before it ends its life.
This feature exists from Windows Vista, but it seems that not enough people knows it, so let’s see how can anyone use the Windows API Code Pack to easily integrate ARR in their applications.
More information on the feature can be found at Application Recovery and Restart on MSDN.
Step 1 – When to Register?
The first step is quite obvious, but needs to be said nevertheless. You should register to ARR when the application loads and unregister when the application unloads.
public MainWindow()
{
InitializeComponent();
...
RegisterApplicationRecoveryAndRestart();
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
...
UnregisterApplicationRecoveryAndRestart();
App.Current.Shutdown();
}
The functions RegisterApplicationRecoveryAndRestart
and UnregisterApplicationRecoveryAndRestart
are my functions which we will see on the next step.
Step 2 – How to Register?
Before using the ARR feature, we check that we’re running on Windows Vista or up by using WindowsAPICodePack CoreHelper.RunningOnVista
helper method.
private void RegisterApplicationRecoveryAndRestart()
{
if (!CoreHelpers.RunningOnVista)
{
return;
}
RestartSettings restartSettings =
new RestartSettings(string.Empty, RestartRestrictions.None);
ApplicationRestartRecoveryManager.RegisterForApplicationRestart(restartSettings);
RecoverySettings recoverySettings =
new RecoverySettings(new RecoveryData(PerformRecovery, null), KeepAliveInterval);
ApplicationRestartRecoveryManager.RegisterForApplicationRecovery(recoverySettings);
}
Register for Restart
Then we do two things. First, we register for restart. The Windows Error Reporting component will present the user the restart dialog if the application had an unhandled exception or has been unresponsive for more than 60 seconds.
When registering for restart, we supply an instance of RestartSettings
. The first parameter it gets is the command line arguments that will be used for the restart, in case we want to define some special parameters (like “run in safe mode”). The second parameters is an enum
that allows us to restrict the restart in some cases, for example, we can set RestartRestriction.NotOnReboot
if we don’t want our application to restart if the computer was restarted due to a system update.
Available restrictions are:
Restriction | Meaning |
None | No restart restrictions |
NotOnCrash | Do not restart the process if it terminates due to an unhandled exception. |
NotOnHang | Do not restart the process if it terminates due to the application not responding. |
NotOnPatch | Do not restart the process if it terminates due to the installation of an update. |
NotOnReboot | Do not restart the process if the computer is restarted as the result of an update. |
Register for Recovery
The second thing we do is register for recovery. This means that if the application will need a restart (from the same reasons as before), what function do we want to run to allow later recovery.
When registering for recovery, we supply an instance of RecoverySettings
. The first parameter it gets is the RecoveryData
object, which wraps a delegate to be called and some state parameter that will be passed (in this example, null
). The second parameter is the keep alive interval, which will be explained shortly.
Implementing the Recovery Function
The recovery function should obey some rules in order to avoid the application getting stuck (again) in the recovery function. You must call ApplicationRestartRecoveryManager.ApplicationRecoveryInProgress
every few (mili)seconds (in the example, KeepAliveInterval = 5000
). This tells the ARR mechanism, “I know it takes some time, but don’t worry, I’m still alive and working on the recovery stuff”.
Also, at the end of the recovery function, you must call ApplicationRestartRecoveryManager.ApplicationRecoveryFinished
with a parameter that indicates whether you succeeded in doing the recovery.
private int PerformRecovery(object parameter)
{
try
{
ApplicationRestartRecoveryManager.ApplicationRecoveryInProgress();
...
ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(true);
}
catch
{
ApplicationRestartRecoveryManager.ApplicationRecoveryFinished(false);
}
return 0;
}
Step 3 – How to Unregister
private void UnregisterApplicationRecoveryAndRestart()
{
if (!CoreHelpers.RunningOnVista)
{
return;
}
ApplicationRestartRecoveryManager.UnregisterApplicationRestart();
ApplicationRestartRecoveryManager.UnregisterApplicationRecovery();
}
This is just some cleanup code to properly unregister from Application Recovery and Restart.
That’s it for now,
Arik Poznanski