none
Explorer Activate Event Triggers After Close of Window RRS feed

  • Question

  • We are developing an Outlook 2010 COM AddIn using VS2012, VSTO 3.0 and .NET 4.0.  What we think we’re seeing is Outlook triggering an Explorer.Activate event on a closed window, yet before the Explorer.Close event has occurred.  We are getting an exception in our Explorer.Activate event handler referencing the Outlook.Selection property (presumably) because the Explorer window/object is no longer valid.  Yet, we don’t know it’s invalid because the Explorer.Close event hasn’t triggered.  The problem occurs when two Explorer windows are open, and one of them gets closed. 

    To reproduce the problem: Begin a debug session of Outlook using the code below.  Once the Outlook Explorer (#1) is visible, right-click the Outlook icon on the task bar (Windows 7) and click Microsoft Outlook 2010 to activate another Explorer (#2) window.  Once displayed, set the focus back to Explorer #1 and click the Close icon.  Since Explorer #2 is next in the window Z-order, it becomes active again.  But then #1 is activated once more and we see an Exception on the access of the Outlook.Selection property.  The Explorer.Activate event is then followed by the Explorer.Close event.

    A first chance exception of type 'System.Deployment.Application.DeploymentException' occurred in System.Deployment.dll
    3458579E-A7F5-4765-9F49-EA7181DECD50: WrapExplorer()
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Deactivate()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: WrapExplorer()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Deactivate()
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Activate(enter)
    3458579E-A7F5-4765-9F49-EA7181DECD50: Me.m_Explorer.Selection.Count = 1
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Activate(exit)
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Deactivate()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Activate(enter)
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: Me.m_Explorer.Selection.Count = 1
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Activate(exit)
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Deactivate()
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Activate(enter)
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in OutlookAddIn35.dll
    3458579E-A7F5-4765-9F49-EA7181DECD50: 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 OutlookAddIn35.CEventWrapper.ExplorerWrapper_Activate() in C:\Users\pschlosser\documents\visual studio 2012\Projects\OutlookAddIn35\OutlookAddIn35\ThisAddIn.vb:line 87
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Activate(exit)
    3458579E-A7F5-4765-9F49-EA7181DECD50: ExplorerWrapper_Close()
    3458579E-A7F5-4765-9F49-EA7181DECD50: WrapperClosed()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Activate(enter)
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: Me.m_Explorer.Selection.Count = 1
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Activate(exit)
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Deactivate()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: ExplorerWrapper_Close()
    FCD96E86-0099-4FB6-980C-F3A1C4A94272: WrapperClosed()

    Public Class ThisAddIn
    
        Private WithEvents MyExplorers As Outlook.Explorers
        Private MyEventWrappers As Dictionary(Of String, CEventWrapper) = New Dictionary(Of String, CEventWrapper)()
    
        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)
        End Sub
    
        Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
            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
    
        Private Function WrapExplorer(Explorer As Microsoft.Office.Interop.Outlook.Explorer) As CEventWrapper
            Dim wrappedExplorer As New CEventWrapper(Explorer)
            AddHandler wrappedExplorer.Closed, New WrapperClosedDelegate(AddressOf WrapperClosed)
            MyEventWrappers(wrappedExplorer.ID) = wrappedExplorer
            wrappedExplorer.TraceCaller()
            Return wrappedExplorer
        End Function
    
        Private Sub WrapperClosed(ID As String)
            Diagnostics.Debug.Print("{0}: WrapperClosed()", ID)
            MyEventWrappers.Remove(ID)
        End Sub
    
    End Class
    
    Public Delegate Sub WrapperClosedDelegate(id As String)
    
    Friend Class CEventWrapper
    
        Private m_guid As String
        Private m_Explorer As Outlook.Explorer
    
        Public Event Closed As WrapperClosedDelegate
    
        Public Property ID() As String
            Get
                Return m_guid
            End Get
            Private Set(value As String)
                m_guid = value
            End Set
        End Property
    
        Protected Sub OnClosed()
            RaiseEvent Closed(ID)
        End Sub
    
        Public Sub New(_explorer As Outlook.Explorer)
            If _explorer Is Nothing Then
                Throw New ArgumentNullException("explorer")
            End If
            m_Explorer = _explorer
            m_guid = Guid.NewGuid().ToString().ToUpper()
            AddHandler Me.m_Explorer.Activate, AddressOf ExplorerWrapper_Activate
            AddHandler Me.m_Explorer.Close, AddressOf ExplorerWrapper_Close
            AddHandler Me.m_Explorer.Deactivate, AddressOf ExplorerWrapper_Deactivate
        End Sub
    
        Friend Sub ExplorerWrapper_Close()
            Me.TraceCaller()
            RemoveHandler Me.m_Explorer.Activate, AddressOf ExplorerWrapper_Activate
            RemoveHandler Me.m_Explorer.Close, AddressOf ExplorerWrapper_Close
            RemoveHandler Me.m_Explorer.Deactivate, AddressOf ExplorerWrapper_Deactivate
            m_Explorer = Nothing
            GC.Collect()
            GC.WaitForPendingFinalizers()
            OnClosed()
        End Sub
    
        Friend Sub ExplorerWrapper_Activate()
            Me.TraceCaller("enter")
            Dim Selection As Outlook.Selection = Nothing
            Try
                Selection = Me.m_Explorer.Selection
                Me.Trace("Me.m_Explorer.Selection.Count = {0}", Selection.Count)
            Catch ex As Exception
                Me.Trace("Exception: {0}", ex.ToString)
            Finally
                If Selection IsNot Nothing Then
                    Runtime.InteropServices.Marshal.ReleaseComObject(Selection)
                    Selection = Nothing
                End If
            End Try
            Me.TraceCaller("exit")
        End Sub
    
        Friend Sub ExplorerWrapper_Deactivate()
            Me.TraceCaller()
        End Sub
    
        Private Sub Trace(format As String, ParamArray args As Object())
            Diagnostics.Debug.Print(Me.m_guid + ": " + format, args)
        End Sub
    
        Friend Sub TraceCaller(Optional message As String = "")
            Dim StackTrace As Diagnostics.StackTrace = New System.Diagnostics.StackTrace()
            Dim Frame As Diagnostics.StackFrame = StackTrace.GetFrame(1)
            Me.Trace("{0}({1})", Frame.GetMethod().Name, message)
            Frame = Nothing
            StackTrace = Nothing
        End Sub
    
    End Class



    Thursday, January 30, 2014 4:24 PM

Answers

  • Update:  We are still seeing an Explorer.Activate event occur after the user clicks the close icon of the Explorer window and the Explorer.Deactivate event has fired.  And we still see a fault referencing Explorer.Selection under those conditions.  We've come to the conclusion, however, the Explorer.Selection property is not necessarily valid during all Explorer.Activate events.

    To demonstrate, change the Outlook.Explorer view over to the "Outlook Today" view, depicting in default configurations: email summary, calendar and task events.  In this view, there really isn't anything to "select."  As such, the same exception occurs on use of the Explorer.Selection property during the Explorer.Activate event.

    Our work-around is a redesign storing the selection criteria during the Explorer.SelectionChange event.  Then during the Explorer.Activate event, instead of accessing the Explorer.Selection property directly, we use the stored data.

    Problem solved...

    for now.



    Tuesday, February 11, 2014 4:11 PM

All replies

  • From the description of ExplorerEvents_10_Event.Activate event,

    Occurs when an explorer becomes the active window, either as a result of user action or through program code.

    I think when you close the second explorer window, it will fire this event. 

    Which exception do you get?

    >>because the Explorer window/object is no longer valid<<

    I think the event sender of Explore window is not the one you closed but the window which activate.

    Friday, January 31, 2014 4:23 AM
  • From the description of ExplorerEvents_10_Event.Activate event,

    Occurs when an explorer becomes the active window, either as a result of user action or through program code.

    I think when you close the second explorer window, it will fire this event. 

    Thanks for replying, BoBo.

    Yes, the Close() event DOES fire after the window closes, but it also fires another Activate() event just prior, and it's within the Activate() event the exception is thrown.

     

    Which exception do you get?

    >>because the Explorer window/object is no longer valid<<

    The exception is shown in log of the initial post.  It reads:

    The Explorer has been closed and cannot be used for further operations.
    Review your code and restart Outlook.

    The code and event handler are also shown in the first post.

    If you will review the log in the first post, we can see there are two Explorer windows.  Explorer #1  has a GUID of 34….50, and #2 has a GUID of FC….72.

    So, running through the sequence:

    1. User begins debug session of Outlook and the COM AddIn shown in the post.
    2. Exp1 opens and events get wrapped.
    3. User then opens a second Outlook window.
    4. Exp1 deactivates while Exp2 opens.
    5. Exp2 events get hooked.
    6. User then clicks back onto Exp1 and it becomes foreground window.
    7. Exp1 is activated and we see the Activate() event fire.
    8. User clicks the close icon on Exp1 and we see the Deactivate() event fire.  Note, Exp1 is no longer visible on the desktop.
    9. Exp2 is next in the window z-order and its Activate() event fires and it gets the focus.
    10. But then we see Exp2 Deactivate() event fire.
    11. Exp1 Activate() event fires, and an exception is thrown.
    12. Exp1 Close() event fires and events are unhooked.
    13. Exp2 is next in z-order and gets focus.  Exp2 Activate() event fires.
    14. User closes Outlook (Exp2) to end the test.
    I think the event sender of Explore window is not the one you closed but the window which activate.

    We hear what you’re saying about closing the wrong window, but we don’t think that’s the case.  Try it yourself.  Even so, how is it possible for the user to Activate() an Explorer window that isn’t valid?  All the user code of the AddIn is shown in the original post.  Perhaps we're overlooking something?

    Friday, January 31, 2014 3:53 PM
  • Update:  We are still seeing an Explorer.Activate event occur after the user clicks the close icon of the Explorer window and the Explorer.Deactivate event has fired.  And we still see a fault referencing Explorer.Selection under those conditions.  We've come to the conclusion, however, the Explorer.Selection property is not necessarily valid during all Explorer.Activate events.

    To demonstrate, change the Outlook.Explorer view over to the "Outlook Today" view, depicting in default configurations: email summary, calendar and task events.  In this view, there really isn't anything to "select."  As such, the same exception occurs on use of the Explorer.Selection property during the Explorer.Activate event.

    Our work-around is a redesign storing the selection criteria during the Explorer.SelectionChange event.  Then during the Explorer.Activate event, instead of accessing the Explorer.Selection property directly, we use the stored data.

    Problem solved...

    for now.



    Tuesday, February 11, 2014 4:11 PM