none
How to properly deal with objects when casting a Word Document from an Outlook Inspector object. RRS feed

  • Question

  • I have found that from the currently Selected Item (e.g. mailItem) in an Explorer window I can get the Word Document.

    This means on the currently selected item I call the "GetInspector" method and the object model gives me one.  From there I can get the Word Object.  No inspector window exists or can be seen at this point, just the Explorer.

    I have noticed that when I do this the "NewInspector" event is raised.

    My first question is that as Outlook has raised the NewInspector event do I need to call "Close" on this inspector instance I have?

    Currently I was doing the following;

    'Class Variable

    Private wDoc as Word.Document

    'somewhere in the class

    wDoc = oInspector.WordEditor

    oInspector.Close(olDiscard) ReleaseComObject(oInspector) oInspector = Nothing

    My second question is that if I do this with a mailItem I have no issues.  If I do this with for example a taskItem.  When I later go and use the class declared wDoc variable then I get an "Object has been deleted" error.

    Wednesday, January 4, 2017 12:27 PM

Answers

  • Hi Edward, that still will not work. The reason being that if my code creates an Inspector and then the user opens that Outlook item, the same inspector is used.  Thus my code would close this window.

    Further as is explained by Microsoft GetInspector Method

    "If an Inspector object already exists for the item, the GetInspector property will return that Inspector object instead of creating a new one."

    Thus if the reverse happens and I call GerInspector on an item that is already open, I have no idea of knowing how the inspector came to exist. (I suppose in this case I could check the new inspector event)

    And another interesting complication is that if the user both opens and closes one of the inspectors I hold, then calling Close on this also produces and error.

    So the answer to my questions is:

    If you call the GetInspector method you are responsible for making sure that it is closed provided the user has not also "used" the inspector.

    In my opinion the Inspector object has no properties to indicate whether it has been or was opened by the user vs opened by the GetInspector method. Thus as is already recommended for Outlook you will need to write a wrapper for Inspectors and hold a list of all of your Wrappers.  In your wrapper you need to listen to the Inspector's Activate event and have a Public Boolean IsActivated which is set to true if the event fires.  Further of course when an Inspector closes you need to listen to the close event and remove your Wrapper from your list of wrappers.

    Then when you are holding an Inspector object which you obtained from the GetInspector method and you want to "dispose" of it you will need to loop through your list of wrappers, for each one check if the Wrapper.Inspector is the inspector you have. If you do not find it, then it is closed already by the user.  If you find it then check the Wrapper.IsActivated boolean. If true then it has been or is already opened by the user, do not close this one either.  If IsActivated is false then call Close.

    • Marked as answer by donky73 Monday, January 9, 2017 2:58 PM
    Monday, January 9, 2017 6:43 AM

All replies

  • Hi donky73,

    >> My first question is that as Outlook has raised the NewInspector event do I need to call "Close" on this inspector instance I have?

    In my option, there is no need for you to close object if it is raised by Outlook itself.

    >> When I later go and use the class declared wDoc variable then I get an "Object has been deleted" error.

    Based on this error, it is obvious that the object has been deleted by you. I would suggest you remain it and let Outlook itself handle it.

    In addition, if you still have error after removing “Close” code, it would be helpful if you could share us complete code which could reproduce your issue.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, January 5, 2017 8:00 AM
  • Here is the code from a ThisAddin.vb file which I believe if you just start a new Outlook Addin project you can just replace this text with what is automatically created.

    Add a reference to MS Word.

    I did this with VS 2012 on Office 2010

    1. First note that with the parts commented out that as you make new selections the number of inspectors keeps rising, this can also be seen for example in Spy++
    2. If you then uncomment the code I have commented then the inspector is closed. BUT if the selection is a mailItem then the word document has no issues, but if it is for example a Task Item then the word document gets destroyed.

    Imports Microsoft.Office.Interop.Word
    
    Public Class ThisAddIn
    
        Private WithEvents olExpl As Outlook.Explorer
    
        Private WithEvents olInsps As Outlook.Inspectors
    
    
        Private Sub ThisAddIn_Startup() Handles Me.Startup
    
            olExpl = Me.Application.ActiveExplorer
            olInsps = Me.Application.Inspectors
    
        End Sub
    
        Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
    
        End Sub
    
        Private Sub olExpl_SelectionChange() Handles olExpl.SelectionChange
    
            Dim olSel As Outlook.Selection = olExpl.Selection
    
            If olSel Is Nothing Then
                Return
            End If
    
            If olSel.Count <> 1 Then
                Return
            End If
    
            Dim oItem As Object = olSel.Item(1)
    
            Dim olIns As Outlook.Inspector = oItem.GetInspector()
    
            '''''' UNCOMMENT THIS
            '' THE INSPECTOR COUNT NO LONGER INCREASES BUT NOTICE THAT THE WORD OBJECT IS DEALT WITH DIFFERENTLY BETWEEN A MAILITEM AND FOR EXAMPLE A TASK OR CALENDAR
            'Dim wDoc As Document = olIns.WordEditor
    
            'Diagnostics.Debug.Print(wDoc.Name)
    
            'Try
            '    olIns.Close(Outlook.OlInspectorClose.olDiscard)
            'Catch ex As Exception
            '    Diagnostics.Debug.Print(ex.ToString)
            'End Try
    
    
            'Try
            '    Diagnostics.Debug.Print(wDoc.Name)
            'Catch ex As Exception
            '    Diagnostics.Debug.Print(ex.ToString)
            'End Try
    
        End Sub
    
        Private Sub olInsps_NewInspector(Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles olInsps.NewInspector
    
            Diagnostics.Debug.Print(olInsps.Count.ToString)
    
        End Sub
    End Class
    

    Thursday, January 5, 2017 10:49 AM
  • Hi donky73,

    Thanks for more information. I made a test with your code under Office 2010, and I could reproduce your issue.

    For a workaround, I would suggest you close the Inspector which you did not use. Here is a simple code.

    Private Sub olExpl_SelectionChange() Handles olExpl.SelectionChange
    
            Dim olSel As Outlook.Selection = olExpl.Selection
    
            If olSel Is Nothing Then
                Return
            End If
    
            If olSel.Count <> 1 Then
                Return
            End If
    
            Dim oItem As Object = olSel.Item(1)
    
            Dim olIns As Outlook.Inspector = oItem.GetInspector()
    
            '''''' UNCOMMENT THIS
            '' THE INSPECTOR COUNT NO LONGER INCREASES BUT NOTICE THAT THE WORD OBJECT IS DEALT WITH DIFFERENTLY BETWEEN A MAILITEM AND FOR EXAMPLE A TASK OR CALENDAR
            Dim wDoc As Document = olIns.WordEditor
    
            Diagnostics.Debug.Print(wDoc.Name)
            'For i = 1 To olInsps.Count - 2
            '    olInsps(i).Close(Outlook.OlInspectorClose.olDiscard)
            'Next
            For Each ins As Outlook.Inspector In olInsps
                If ins.Caption <> olIns.Caption Then
                    ins.Close(Outlook.OlInspectorClose.olDiscard)
                End If
            Next
            Diagnostics.Debug.Print(wDoc.Name)
            'Try
            'olIns.Close(Outlook.OlInspectorClose.olDiscard)
            'Catch ex As Exception
            '    Diagnostics.Debug.Print(ex.ToString)
            'End Try
    
    
            'Try
            'Diagnostics.Debug.Print(wDoc.Name)
            'Catch ex As Exception
            '    Diagnostics.Debug.Print(ex.ToString)
            'End Try
    
        End Sub
    

    In addition, I made a test with Office 2013, and this issue did not exist, I would suggest you upgrade your Office to Office 2013.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, January 6, 2017 7:29 AM
  • Thanks for the feedback, the problem with closing is that you close Inspectors. How do you know how these inspectors came to exist? Maybe the user has actually opened an Outlook item. When we close our inspector we need to know it's one that we have generated from the Getinspector method and not one that was already or has been opened by the user. What property of inspector helps us here?
    Friday, January 6, 2017 2:22 PM
  • Hi donky73,

    As my above code, you could try Inspector.Caption Property or Inspector.CurrentItem Property (Outlook).

    You could store all the captions of the Inspectors which are opened by your code, and then close them according the captions.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, January 9, 2017 4:55 AM
  • Hi Edward, that still will not work. The reason being that if my code creates an Inspector and then the user opens that Outlook item, the same inspector is used.  Thus my code would close this window.

    Further as is explained by Microsoft GetInspector Method

    "If an Inspector object already exists for the item, the GetInspector property will return that Inspector object instead of creating a new one."

    Thus if the reverse happens and I call GerInspector on an item that is already open, I have no idea of knowing how the inspector came to exist. (I suppose in this case I could check the new inspector event)

    And another interesting complication is that if the user both opens and closes one of the inspectors I hold, then calling Close on this also produces and error.

    So the answer to my questions is:

    If you call the GetInspector method you are responsible for making sure that it is closed provided the user has not also "used" the inspector.

    In my opinion the Inspector object has no properties to indicate whether it has been or was opened by the user vs opened by the GetInspector method. Thus as is already recommended for Outlook you will need to write a wrapper for Inspectors and hold a list of all of your Wrappers.  In your wrapper you need to listen to the Inspector's Activate event and have a Public Boolean IsActivated which is set to true if the event fires.  Further of course when an Inspector closes you need to listen to the close event and remove your Wrapper from your list of wrappers.

    Then when you are holding an Inspector object which you obtained from the GetInspector method and you want to "dispose" of it you will need to loop through your list of wrappers, for each one check if the Wrapper.Inspector is the inspector you have. If you do not find it, then it is closed already by the user.  If you find it then check the Wrapper.IsActivated boolean. If true then it has been or is already opened by the user, do not close this one either.  If IsActivated is false then call Close.

    • Marked as answer by donky73 Monday, January 9, 2017 2:58 PM
    Monday, January 9, 2017 6:43 AM