September 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Build Build Resilient Applications with Windows Recovery and Restart Applications

  • September 2, 2009
  • By Nick Wienholt
  • Send Email »
  • More Articles »

Recovering Data

Application Recovery allows an application to register a callback function with Windows that will be called if the application becomes unresponsive (which is defined as failing to respond to Windows messages within five seconds) or experiences an unhandled error. The callback function provides the application with a chance to recover and store user-entered data before the process exits. It is generally a good idea to periodically backup the data a user is entered, because that increases the likelihood that data will be in a good state for recovery in the event of an application error. To register for application recovery, make a simple call to RegisterApplicationRecoveryCallback:

//inside application start-up code
RegisterApplicationRecoveryCallback(SaveData, 
   NULL, 2000, 0);
//elsewhere is application
DWORD WINAPI SaveData(PVOID pContext)
{
   //see sample code download for details
   CreateRestoreLocation(); 
   //check whether the user has cancelled 
   // the restore process
   BOOL canceled = FALSE;
   ApplicationRecoveryInProgress(&canceled);
   if (canceled)
      return 0;
   //save user data
   HANDLE hFile = CreateFile(
      GetRestoreFileName().c_str(), 
      GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
      FILE_ATTRIBUTE_NORMAL, NULL);
   wstring fileData(
      L"Data that was recovered before crash");
   DWORD bytesWritten;
   WriteFile(hFile, fileData.data(), 
      fileData.length() * 
      sizeof(wchar_t), &bytesWritten, NULL);
   CloseHandle(hFile);
   //tell the operating system that recovery 
   // is complete
   ApplicationRecoveryFinished(TRUE);
 
   return 0;
}

In the preceding code, the call to RegisterApplicationRecoveryCallback specifies the recovery function and lets you provide any parameters that should be passed to the recovery function. The third parameter (2000) is the ping interval of the recovery procedure. During recovery, the recovery procedure must call ApplicationRecoveryInProgress at least once every ping interval to let the operating system know that recovery is still underway.

As shown in the SaveData function above, the ApplicationRecoveryInProgress serves double duty; it's also used to determine whether the user has cancelled application recovery. When Windows calls the recovery function, it displays a dialog like the one shown in Figure 3.


Figure 3. Recovery Dialog:
Users see this dialog after a crash when an application has been registered for recovery.

Note that users can choose to cancel the recovery process if they decide it is taking too long or that the data they have entered is not worth recovering. After data recovery is complete, the recovery function should call ApplicationRecoveryFinished to inform Windows of the success of the data recovery process.

If an application uses both restart and recovery, the API determines whether an application should recover data that was saved during a recovery operation using the command line parameters passed to RegisterApplicationRestart. By specifying a restart command-line switch, start-up code can easily determine whether an attempt should be made to read recovery data from a file. In the code below, the restart command line switch is /r. When this command-line switch is detected, the application makes an attempt to read recovered data is made.

//check to see if we are recovering from a crash
 const wstring restartSwitch(L"\\r");
 const wstring commandLine(lpCmdLine);
 if (commandLine.find(restartSwitch) != wstring::npos){
  //recover data saved before crash
  HANDLE hFile = CreateFile(GetRestoreFileName().c_str(),
   GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  if (hFile){
   const int buffSize = 256;
   wchar_t buff[buffSize];
   ZeroMemory(buff, buffSize * sizeof(wchar_t));
   DWORD bytesRead;
   if (ReadFile(hFile, buff, buffSize * sizeof(wchar_t), 
    &bytesRead, NULL)){
    wstring userMsg(L"Data recovered after recovery:\n");
    userMsg.append(buff);
    //display recovered data to user
    MessageBox(NULL, userMsg.c_str(), L"Recovery", MB_OK);
   }
   CloseHandle(hFile);
   DeleteFile(GetRestoreFileName().c_str());
  }
 }
 //register for restart
 RegisterApplicationRestart(restartSwitch.c_str(), 0);

The sample application uses one global file name for storing recovery information, but using a per-process file name can be achieved by using a unique file name for each instance of the application, passing this as a re-start command line to RegisterApplicationRestart, and retrieving and reading this file when the application is restarted by Windows. If application recovery is used without application restart, the recovery file needs to be either stored at a well-known location that is checked each time the application starts, or the recovery function can store the name of the recovery file in the registry and this registry key can be checked on each application start.

Application Restart and Recovery gives application developers a consistent and simple way to deal with reliability and data recovery in the applications they create. Application crashes invariably create a bad impression, but by gracefully recovering the data that the user has entered and restarting the application with the saved data file open and the application ready for use again, you can save your end users from much of the pain and angst associated with application crashes.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel