Novel way to handle Outlook 2010 Fast Shutdown

In order to understand how Outlook’s Fast Shutdown mechanism affects your Outlook Add-ins, I have made a utility to test and demonstrate Outlook 2010 fast shutdown mechanism and an example Outlook Add-in.

Fast Shutdown Utility

The Fast Shutdown Exercise Machine Utility “FSU” is a tray-area application written in Delphi 2009 (Unicode) with best practices. It loads and saves into \Application Data\ or \AppData\ location in your user account using XML instead of Registry or INI files.

Tab 1 Global: This controls global startup settings. FSU detects both 32-bits and 64-bits Outlook. It reads and writes both 32-bit and 64-bit registry locations.

You can select from four different shutdown options: Enabled, Opt-in, Disabled and Default. This corresponds to [Software\Microsoft\Office\14.0\Outlook\Options\Shutdown\FastShutdownBehavior:DWORD] entry in the Windows Registry.

Fast Shutdown Utility: Global tab

Tab 2 Individual Add-ins: Inclusive of global settings, you can select Enable Shutdown Notification for all Add-ins or default settings, along with individual settings for each Add-in.

Fast Shutdown Utility: Individual Add-ins tab

Tab 3 Utility: In order to simulate more annoying Outlook and Word situations, there is ability to kill Outlook processes in memory, make Outlook hidden, make Word sessions hidden and kill Word processes in memory.

Fast Shutdown Utility: Individual Utility tab

Tab 4: About is the About page. This tab contains the copyright notice and link to this article.

Fast Shutdown Utility: Individual About  tab

Outlook Add-in example

I've developed an example Outlook Add-in to get ready for Outlook 2010 and discovered a novel way to handle Outlook Fast Shutdown 2010.

The software used to develop this Add-in and additional components are:

64-bit, 32-bit registry on Windows 7, Windows 2008 Server

Using Delphi 2009 / Delphi 2010 we use the function OutlookVersion64 to detect if 64-bit Outlook is installed or else use OutlookVersion to find the Outlook version

function OutlookVersion64: string;
var
  sVer, sTmp: string;
const
  sOutlookDefault = 'Not Installed';
  sOutlook14 = 'Outlook.Application.14'; // first 64-bit version
begin
  sVer := sOutlookDefault;
  with TRegistry.Create() do
    try
      // 64-bit Outlook
      Access := KEY_WOW64_64KEY or KEY_READ;
      RootKey := HKEY_CLASSES_ROOT;
      if OpenKey('Outlook.Application.14', false) then
      begin
        sVer := sOutlook14;
      end;
    finally
      free
    end;
  Result := sVer;
end;

Note the usage of KEY_READ to allow read-only access to HKEY_CLASSES_ROOT (required when the user is not an Administrator) and KEY_WOW64_64KEY to access 64-bit portions of Windows Registry.

//Detects Outlook version for 32-bit Machines
function OutlookVersion: string;
var
  sVer, sTmp: string;
  reg: TRegistry;
const
  sOutlookDefault = 'Not Installed';
  sOutlook14 = 'Outlook.Application.14';
  sOutlook12 = 'Outlook.Application.12';
  sOutlook11 = 'Outlook.Application.11';
  sOutlook10 = 'Outlook.Application.10';
  sOutlook9 = 'Outlook.Application.9';
  sOutlook8 = 'Outlook.Application.8';
begin
  sVer := sOutlookDefault;
  reg := TRegistry.Create(KEY_READ);
  reg.RootKey := HKEY_CLASSES_ROOT;
  if reg.OpenKey('Outlook.Application\CurVer\', false) then
  begin
    sTmp := reg.ReadString('');
    if sTmp = sOutlook14 then
      sVer := sOutlook14
    else if sTmp = sOutlook12 then
      sVer := sOutlook12
    else if sTmp = sOutlook11 then
      sVer := sOutlook11
    else if sTmp = sOutlook10 then
      sVer := sOutlook10
    else if sTmp = sOutlook9 then
      sVer := sOutlook9
    else if sTmp = sOutlook8 then
      sVer := sOutlook8;
  end;
  reg.free;
  Result := sVer;
end;

Novel method to alleviate Fast Startup issue

Issue Before Fast Startup After Fast Startup
Saving of toolbars Code written in OnShutDown Redirect to semaphore and specific routine (see below)
Database Code written in OnDisconnect
Registry or INI settings save Code written in OnShutDown
Additional clean-ups from your program Code written in OnDisconnect

When should I use OnShutDown and OnDisconnect?
OnShutDown, the toolbars, certain registry values are present. Thus, if you wrote your own toolbar customizations and need to save those values to registry, you should use OnShutDown. When you close your own final settings (e.g., the database connection, freeing custom objects in your own list) you should use OnDisconnect.

  OnShutDown OnDisconnect
Outlook Pointers Present (e.g., Toolbars, etc.). Opportunity to save GUI changes. May not be present. They are 0x000000 (null) or values may have changed.
(Accessing any NULL variables may cause 0x8000ffff catastrophic failure error message or various COM error messages)
Your Database Connection, Registry key saving, DLL unloading Database connection may have unsaved data.
DLLs may be locked.Questions:
Try to unload any DLLs when not in use during processing finish (after loading DLL)Is a persistent database connection truly necessary?
Where you unload your DLLs, close database connection.
(Suggestion: Move codes to OnShutDown instead)

The flowchart for pre-Outlook 2010 is:

Flowchart for pre-Outlook 2010

You write your code in OnShutDown/OnBeginShutDown (1) and OnDisconnect/OnAddinFinalize (3).

Flowchart for pre-Outlook 2010

With Outlook 2010 it is:

Flowchart for Outlook 2010

Refactoring steps are:

  1. You would place an event sink to capture the OnQuit event from Outlook and start Shutdown processing.
    There is a semaphore to guard against Shutdown twice.
  2. Since OnShutDown is called, if the semaphore is not set, it will call the Shutdown code.

This code change handles every situation:

Testing from Fast Shutdown Utility Logic
Outlook 2010 with Fast Shutdown or Opt-in
  1. Your Addin traps the OnQuitEvent
  2. Shutdown processing occurs
  3. The semaphore is set to guard against duplicate shutdown
    (OnShutDown, OnDisconnect is not called)
  4. End of process
Outlook 2010 with Fast Shutdown disabled
  1. Your Addin traps the OnQuitEvent
  2. Shutdown processing occurs
  3. The semaphore is set to guard against duplicate shutdown
  4. OnShutDown is called, but since the semaphore is set, the routine returns immediately.
  5. End of process
Outlook 2007, Outlook 2003
  1. Your Addin traps the OnQuitEvent
  2. Shutdown processing occurs
  3. The semaphore is set to guard against duplicate shutdown
  4. OnShutDown is called, but since the semaphore is set, the routine returns immediately.
  5. End of process

Code

The interface code is:

TAddInModule = class(TadxCOMAddInModule)
    dataconn: TADOConnection;
    adxOutlookAppEvents1: TadxOutlookAppEvents;
    procedure adxCOMAddInModuleCreate(Sender: TObject);
    procedure adxOutlookAppEvents1Quit(Sender: TObject);
    procedure adxCOMAddInModuleAddInBeginShutdown(Sender: TObject);
    procedure adxCOMAddInModuleAddInFinalize(Sender: TObject);
  private
  protected
  public
    bFastShutdown: Boolean; // Semaphore
    procedure MergedClose;
  end;

The implementation code is:

procedure TAddInModule.adxCOMAddInModuleCreate(Sender: TObject);
begin
  bFastShutdown := false; // Initialize Fast Shutdown to false
end; 
 
procedure TAddInModule.adxCOMAddInModuleAddInBeginShutdown(Sender: TObject);
begin
  MergedClose; // Call new procedure instead
end; 
 
procedure TAddInModule.adxCOMAddInModuleAddInFinalize(Sender: TObject);
begin
  //Nothing to do
end; 
 
procedure TAddInModule.adxOutlookAppEvents1Quit(Sender: TObject);
begin
  MergedClose; // Call new procedure instead
end; 
 
procedure TAddInModule.MergedClose;
begin
  if bFastShutdown then  // Semaphore to prevent Shutdown called twice.
    Exit;
  bFastShutDown := true;
  // Save toolbars
  // Free any memory
  // Close any pending database connection (if file-based)
end;

References:

1Icons were used from https://www.wpclipart.com/ (public domain license)

Available downloads:

Fast Shutdown Utility
Sample Outlook add-in

You may also be interested in:

Outlook Fast Shutdown: under the yellow hood
Outlook 2010 Fast Shutdown feature

Post a comment

Have any questions? Ask us right now!