Reputation: 883
When Outlook exits, any events registered for via PIA will be lost, and any PIA objects that are currently in memory will be inaccessible.
Here is a simple console app that illustrates the issue at hand:
static void Main(string[] args)
{
var outlookApp = new Application();
var ns = outlookApp.GetNamespace("MAPI");
var calendar = ns.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
var appointment = (AppointmentItem) calendar.Items.GetFirst();
((ApplicationEvents_11_Event) outlookApp).Quit +=
() => Console.WriteLine("Outlook is quitting");
while (true)
{
Console.WriteLine("Explorers: " + outlookApp.Explorers.Count);
Console.WriteLine("Folders: " + ns.Folders.Count);
Console.WriteLine("Items: " + calendar.Items.Count);
Console.WriteLine("Start date: " + appointment.Start);
Thread.Sleep(2000);
}
}
When I run this application, it starts up an instance of Outlook in a separate process (shown in the system tray) if Outlook isn't already running. There are three scenarios that I know of that can cause the Quit
event to fire:
Each of these has the same effect on my program: The Quit
event is fired, and then one of my attempts to access an Outlook object fails with a COMException
.
What is the standard or recommended way to deal with this? Theoretically, the application exit could happen asynchronously at any time. Do I need to catch COMException
on any operation that uses PIA and restart the operation from the call to new Application()
if that exception occurs? That could be tricky, depending on the complexity of the operation.
What about event handlers? Do I need to keep track of all event handlers that I have added to Outlook objects and then re-add them if I receive an Application.Quit
event?
What about the UX? Suppose the user selected Exit Now from the context menu of the system tray, and then the icon instantly reappears because my application detected the exit and re-initialized everything. Should I pop up some kind of dialog to the user informing them that I need Outlook for my application to operate properly?
What about in a system shutdown situation? Presumably I would receive a SystemEvents.SessionEnding
event before I receive an Application.Quit
from Outlook. Is that guaranteed, or should I wait some amount of time before restoring communications to see if the system is in the process of going down? Is there some other way to detect if we are in a session ending state?
Apologies for the multi-faceted question. Links to reading material are welcome if there is an article that already addresses this topic. I haven't found one after a good amount of searching.
Upvotes: 0
Views: 118
Reputation: 66255
If Application.Quit does not fire, you can hook up Explorer.Close and Inspector.Close events and check if Aplication.Explorers.Count and Aplication.Inspectors.Count are both 0 (or 1 since the event you are processing still has the window open).
To hook up these events, track the Application.Explorers.NewExplorer and Application.Inspectors.NewInspector events. To hook up explorers and inspectors already displayed by Outlook, loop through the Application.Explorers and Application.Inspectors collections on startup.
Upvotes: 0