'VSTO Outlook Visual Basic - Handle Mail Item Closure

I'm creating an Outlook Add-In, and am struggling to detect and handle the event when a mail item is closed. The inspectors_NewInspector function is triggered sucessfully (as I can obtain the subject and sender of the email), but I cannot get the mailItem_close() function to be called at all.

        
Public Class ThisAddIn
    Public WithEvents inspectors As Outlook.Inspectors
    Public WithEvents mailItem As Outlook.MailItem

    Private Sub ThisAddIn_Startup() Handles Me.Startup
        inspectors = Me.Application.Inspectors
    End Sub

    Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown

    End Sub
    Private Sub inspectors_NewInspector(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles inspectors.NewInspector
        If Inspector.CurrentItem.size > 0 And Inspector.CurrentItem.class = 43 Then
            mailItem = Inspector.CurrentItem
            Dim mSubject As String = mailItem.Subject
            Dim mFrom As String = mailItem.SenderEmailAddress
            Dim mTime As String = mailItem.ReceivedTime
            'MsgBox(mSubject)
        End If
    End Sub

    Private Sub mailItem_Close()
        MsgBox("closing")
    End Sub


Solution 1:[1]

It seems you have copied the code from VBA to a VB.NET add-in. In add-ins you need to use the AddHandler method to attach an event handler programmatically, see How do I create an event handler for a programmatically created object in VB.NET? for more information.

Note, each time the NewInspector event is fired the mailItem is overwritten, so the previous item instance is lost and can't fire events:

Private Sub inspectors_NewInspector(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles inspectors.NewInspector
        If Inspector.CurrentItem.size > 0 And Inspector.CurrentItem.class = 43 Then
            mailItem = Inspector.CurrentItem
            Dim mSubject As String = mailItem.Subject
            Dim mFrom As String = mailItem.SenderEmailAddress
            Dim mTime As String = mailItem.ReceivedTime
            'MsgBox(mSubject)
        End If
    End Sub

    Private Sub mailItem_Close()
        MsgBox("closing")
    End Sub

Instead, you need to maintain a list or array of items, so each time the NewInspector event is fired you will add an item to the list to keep the reference alive, so the events will be fired.

You may find the Implement a wrapper for inspectors and track item-level events in each inspector article helpful.

Solution 2:[2]

With huge thanks to Eugene, the solution was indeed to use AddHandler.

       
    Private Sub inspectors_NewInspector(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles inspectors.NewInspector
        If Inspector.CurrentItem.size > 0 And Inspector.CurrentItem.class = 43 Then
            inspectorEvents = TryCast(Inspector, Outlook.InspectorEvents_Event)
            AddHandler inspectorEvents.Close, AddressOf inspectorEvents_Close
        End If
    End Sub

    Public Sub inspectorEvents_Close()
        Dim currentInspector As Outlook.Inspector
        currentInspector = Application.ActiveInspector
        mailItem = currentInspector.CurrentItem
        Dim mSubject As String = mailItem.Subject
        Dim mFrom As String = mailItem.SenderEmailAddress
        Dim mTime As String = mailItem.ReceivedTime
        MsgBox("closing" & mSubject)
    End Sub

I'm occasionally getting multiple close handlers firing when a mail message is closed, but I should be able to get around that by maintaining an array / list of inspector ids and ensuring only one is created per mail item.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Eddie Clements