none
How To Handle Multiple Outlook Application Instances RRS feed

  • Question

  • We’re developing an Outlook 2010 COM AddIn using Visual Studio 2012 and VSTO 3.0.  We have a global instance of the Office.IRibbonUI and depending upon the messages selected in the Inbox, or the message viewed in the active Outlook.Inspector, we enable and disable a custom ReplyTo button in our Ribbon Tab.  Since our Ribbon Tab is global, as the user switches between the main Explorer window and one or more Inspector windows, the conditions affecting the Ribbon change.  When the user switches back, the changed Ribbon may not match the conditions of the Explorer or Inspector window.  To address this, we handle the Explorer.Activate and the Inspector.Activate events to reevaluate the Outlook.MailItem selected or viewed and make calls to Office.IRibbonUI.Invalidate() accordingly.

    We’ve run into a problem in our Explorer.Activate event handler where in some cases, the Explorer.Selection property throws an exception because it’s no longer valid.  This problem occurs once a second instance of Outlook 2010 is running and then one of the instances closes.  This appears a complex and tricky problem, but we suspect we don’t handle multiple Application instances correctly. 

    In our ThisAddIn_Startup() function, we hook the Outlook.NewExplorer and Outlook.NewInspector events which, in turn, hook the Explorer.Activate and the Inspector.Activate events when new Explorers and Inspectors are created.  We fear it’s the use of Me.Application in our ThisAddIn_Startup() function that’s the problem, when more than one Outlook.Application instance is present.  Presuming Globals.ThisAddIn is global across multiple instances of the Outlook application, we suspect the MyExplorers and MyInspectors variables get clobbered by subsequent instances.

    One way to solve this problem is to correctly handle multiple instances of the Outlook.Application object in relation to our global variables MyExplorers and MyInspectors.  Another might be to have multiple instances of our Ribbon, eliminating the need to reevaluate conditions.

    Honestly, we’re unsure we understand the source of the problem.  But the same question keeps coming up: How do developers handle multiple Outlook Application instances when trapping the Outlook.NewExplorer and Outlook.NewInspector events if they use Me.Application.Explorers and Me.Application.Inspectors in their ThisAddIn_Startup() functions?
    Public Class ThisAddIn
    
        Private WithEvents MyExplorers As Outlook.Explorers
        Private WithEvents MyInspectors As Outlook.Inspectors
    
        Private Sub ThisAddIn_Startup() Handles Me.Startup
            MyExplorers = Me.Application.Explorers
            For i As Integer = MyExplorers.Count To 1 Step -1
                WrapExplorer(MyExplorers(i))
            Next
            AddHandler MyExplorers.NewExplorer, New Microsoft.Office.Interop.Outlook.ExplorersEvents_NewExplorerEventHandler(AddressOf MyExplorers_NewExplorer)
    
            MyInspectors = Me.Application.Inspectors
            For i As Integer = MyInspectors.Count To 1 Step -1
                WrapInspector(MyInspectors(i))
            Next
            AddHandler MyInspectors.NewInspector, New Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(AddressOf MyInspectors_NewInspector)
        End Sub
    
        Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
            RemoveHandler MyInspectors.NewInspector, AddressOf MyInspectors_NewInspector
            Runtime.InteropServices.Marshal.ReleaseComObject(MyInspectors)
            MyInspectors = Nothing
    
            RemoveHandler MyExplorers.NewExplorer, AddressOf MyExplorers_NewExplorer
            Runtime.InteropServices.Marshal.ReleaseComObject(MyExplorers)
            MyExplorers = Nothing
        End Sub
    
        Public Sub MyExplorers_NewExplorer(Explorer As Microsoft.Office.Interop.Outlook.Explorer)
            WrapExplorer(Explorer)
        End Sub
    
        Public Sub MyInspectors_NewInspector(Inspector As Microsoft.Office.Interop.Outlook.Inspector)
            WrapInspector(Inspector)
        End Sub
    
    End Class



    Wednesday, January 29, 2014 5:29 PM

Answers

  • Outlook is a singleton, you can only have one instance of Outlook running.

    You *can* have multiple Explorers (which you already handle). Do you handle the Explorer.Close event to make sure you never work with a stale explorer?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Wednesday, January 29, 2014 5:32 PM

All replies

  • Outlook is a singleton, you can only have one instance of Outlook running.

    You *can* have multiple Explorers (which you already handle). Do you handle the Explorer.Close event to make sure you never work with a stale explorer?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Wednesday, January 29, 2014 5:32 PM
  • Outlook is a singleton, you can only have one instance of Outlook running.

    You *can* have multiple Explorers (which you already handle). Do you handle the Explorer.Close event to make sure you never work with a stale explorer?

    We *are* handling Explorer.Close.  But we'll take a closer look at it.  We find it surprising we get an Explorer.Activate event on an Explorer that's been closed.

    But it's good news we need not worry about multiple Outlook Applications, because that was making our heads hurt.

    Wednesday, January 29, 2014 6:29 PM
  • Do you get the Activate event after the Close one? Am I on the right avenue?
    Wednesday, January 29, 2014 6:36 PM
  • Do you get the Activate event after the Close one? Am I on the right avenue?

    Yes, you are very close.  When two Outlook Explorer windows are open, we are seeing an Explorer.Activate event occur after the user closes an Explorer window, but before the Explorer.Close event has fired.  Within the Activate event handler, we get an exception on the Explorer.Selection because (presumably) the Explorer is no longer valid.

    One might think we are messing up references to the correct Explorer object.  But the really doesn’t seem the case.

    To reproduce, we launch Outlook and Explorer window #1 displays.  We right-click the Outlook icon on the task bar (of Windows 7 x64), click Microsoft Outlook 2010 and Explorer window #2 is displayed.  We activate #1 and click the close icon.  We then see an Activate on #2. But then an Activate on #1 shortly follows and the exception occurs.

    Each time we wrap an Explorer object, we make a call to Guid.NewGuid() to give us a unique ID we can use in our trace logs to keep track.  Refer to the following log and you may see what we think we are seeing, an Active on a closed Explorer window before the Close event has fired.

    A first chance exception of type 'System.Deployment.Application.DeploymentException' occurred in System.Deployment.dll
    1391008905.224320: ThisAddIn_Startup()
    1391008905.244320: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: WrapApplication()
    1391008905.260320: 1D905674-970B-4F1A-82E6-8A715766C712: WrapExplorer()
    1391008905.271320: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_Startup()
    1391008905.279330: 244A563F-5F49-4E9D-91E9-79F2D58E883B: WrapNamespace()
    1391008905.295330: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_ItemLoad()
    1391008905.301330: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_MAPILogonComplete()
    1391008905.368330: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_ViewSwitch()
    1391008905.371330: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_FolderSwitch()
    1391008905.470340: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008905.485940: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008905.485940: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008905.485940: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008905.517140: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008905.517140: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_ItemLoad()
    1391008906.624740: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008906.640340: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_SelectionChange()
    1391008911.791170: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Deactivate()
    1391008913.956780: E22C3950-C9C3-4196-B530-D01E3B4B633F: WrapExplorer()
    1391008914.066780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_ViewSwitch()
    1391008914.066780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_FolderSwitch()
    1391008914.086780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.086780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.096780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.096780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.106780: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.516790: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008914.526790: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_SelectionChange()
    1391008917.195210: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Deactivate()
    1391008917.242010: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Activate(enter)
    1391008917.257610: Me.Explorer.Selection.Count = 1
    1391008917.257610: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Activate(exit)
    1391008917.257610: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_BeforeMove()
    1391008919.507220: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Deactivate()
    1391008919.522230: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Activate(enter)
    1391008919.527230: Me.Explorer.Selection.Count = 1
    1391008919.527230: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Activate(exit)
    1391008919.579730: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Deactivate()
    1391008919.589730: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Activate(enter)
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in OutlookAddIn34.dll
    1391008919.619730: Exception: System.Runtime.InteropServices.COMException (0x92820009): The Explorer has been closed and cannot be used for further operations. Review your code and restart Outlook.
       at Microsoft.Office.Interop.Outlook.ExplorerClass.get_Selection()
       at OutlookAddIn34.CEventExplorer.ExplorerWrapper_Activate() in c:\users\pschlosser\documents\visual studio 2012\Projects\OutlookAddIn34\OutlookAddIn34\Event Classes\CEventExplorer.vb:line 37
    1391008919.619730: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Activate(exit)
    1391008919.664730: 1D905674-970B-4F1A-82E6-8A715766C712: ExplorerWrapper_Close()
    1391008919.689730: 1D905674-970B-4F1A-82E6-8A715766C712: WrapperClosed()
    1391008919.717230: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Activate(enter)
    1391008919.719730: Me.Explorer.Selection.Count = 1
    1391008919.722230: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Activate(exit)
    1391008922.132510: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Deactivate()
    1391008922.241710: E22C3950-C9C3-4196-B530-D01E3B4B633F: ExplorerWrapper_Close()
    1391008922.257310: E22C3950-C9C3-4196-B530-D01E3B4B633F: WrapperClosed()
    1391008922.257310: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_Quit()
    1391008922.272910: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: ApplicationWrapper_Close()
    1391008922.272910: E7A73EBA-8776-48F3-BCC9-DA821CA0EC3B: WrapperClosed()
    1391008922.288510: 244A563F-5F49-4E9D-91E9-79F2D58E883B: NamespaceWrapper_Close()
    1391008922.288510: 244A563F-5F49-4E9D-91E9-79F2D58E883B: WrapperClosed()

        Friend Overrides Sub ExplorerWrapper_Activate()
            Me.TraceCaller("enter")
            Try
                Me.Print("Me.Explorer.Selection.Count = {0}", Me.Explorer.Selection.Count)
            Catch ex As Exception
                Me.Print("Exception: {0}", ex.ToString)
            End Try
            Me.TraceCaller("exit")
        End Sub


    Wednesday, January 29, 2014 11:48 PM
  • Hello Peter,

    Unfortunately I couldn't reproduce the issue on my machine with Outlook 2013 installed. Most probably you don't release underlying COM objects properly. For example, I see the following line of code above:

    Me.Explorer.Selection.Count

    I suppose the Explorer object is stored in the class field. But each time you get a new Selection object. The Selection property returns an instance of the Selection class.

    Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object.

    Thursday, January 30, 2014 12:31 PM
  • Thanks for the reply, Eugene.

    That's a good thought, but we don't think that's the cause.  While it's true in the simplified exampled shown, the object isn't release properly, but in actual practice it is.  It may be wise to ask a new question, because this looks like an event issue with Explorer and not an Application issue as the title suggests.

    Outlook.Explorer.Activate Event After Close of Window?


    In the new thread, we've provided a more compact (and complete) code sample for those wishing to reproduce.
    Thursday, January 30, 2014 4:28 PM