Vista: RegisterApplicationRecoveryCallback

Thu, August 24, 2006, 05:11 AM under Windows | Vista
We looked previously at RegisterApplicationRestart and that blog entry serves as the introduction to the Application Recovery APIs in Vista so I suggest you read that before continuing below.

To demo this, we'll start with the code we've already created.
f) For both samples, let's offer an additional user option for hanging the application. We can do this via a dedicated button like this:
    // hang
private void button3_Click(object sender, EventArgs e)
{
while (true) { }
}
g) Our pinvoke wrappers cover 3 functions RegisterApplicationRecoveryCallback, ApplicationRecoveryInProgress, ApplicationRecoveryFinished and a helper delegate as shown here:
    [DllImport("kernel32.dll")]
static extern uint RegisterApplicationRecoveryCallback(IntPtr pRecoveryCallback, IntPtr pvParameter, int dwPingInterval, int dwFlags);

[DllImport("kernel32.dll")]
static extern uint ApplicationRecoveryInProgress(out bool pbCancelled);

[DllImport("kernel32.dll")]
static extern uint ApplicationRecoveryFinished(bool bSuccess);

delegate int ApplicationRecoveryCallback(IntPtr pvParameter);
Taking advantage of the APIs involves two functions:
h) First, we register our interest to be called back, by passing in the method that must be called:
    private ApplicationRecoveryCallback mCallback;

// recover
private void button4_Click(object sender, EventArgs e)
{
mCallback = new ApplicationRecoveryCallback(this.RecoverIt);

IntPtr del = Marshal.GetFunctionPointerForDelegate(mCallback);

RegisterApplicationRecoveryCallback(del, IntPtr.Zero, 5000, 1 4);
}
i) Second, we need to write a method that will run our recovery code (I also used a helper method for code clarity):
    private int RecoverIt(IntPtr pvParameter)
{
// just an action that proves this runs
File.Create(Environment.CurrentDirectory + @"\recover.txt").Close();

int i = 4; //random number to simulate delay
while (i != 0)
{
bool b = this.Ping();
if (b) return 0;
Thread.Sleep(3000); //simulates some recovery action
i--;
}

ApplicationRecoveryFinished(true);
return 0;
}

private bool Ping()
{
bool esc;
ApplicationRecoveryInProgress(out esc);
if (esc)
{
MessageBox.Show("Cancelled");
}
return esc;
}
That's all there is to it. Now run your app, and after you have called RegisterApplicationRecoveryCallback, wait for 60 seconds before crashing/hanging the app via the appropriate button. Note how at that instance, in your application's folder an empty file is created (this is proof that your recovery method run).

The other relevant recovery functions that you could pinvoke are UnregisterApplicationRecoveryCallback and GetApplicationRecoveryCallback.
Incidentally, these restart and recovery APIs is what the new Restart Manager is based on.