cancel opening an Outlook item

Add-in Express™ Support Service
That's what is more important than anything else

cancel opening an Outlook item
close the inspector that was passed to AdxOutlookAppEvents1_NewInspector() 
Gordon Prince




Posts: 75
Joined: 2015-04-30
Did all that. msgbox doesn't pop up in Outlook after unregistering the project, the project doesn't show up in the list of Add-ins from Outlook, Options.
Posted 30 Oct, 2015 06:30:42 Top
Andrei Smolin


Add-in Express team


Posts: 14106
Joined: 2006-05-11
I would like to access your PC remotely. Is this possible? If yes, I suggest using TeamViewer; in this case you'll need to send me your session ID and password to the support email address; please find it in {Add-in Express}\readme.txt; make sure your email contains a link to this topic.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 30 Oct, 2015 06:38:19 Top
Gordon Prince




Posts: 75
Joined: 2015-04-30
Sounds good. Thanks.

I've installed TeamViewer. My ID: XXXXXXXXXX. Password XXXX. I'll delete this when we're done.
Posted 30 Oct, 2015 06:53:56 Top
Gordon Prince




Posts: 75
Joined: 2015-04-30
This seems to be working. Does it look reasonable to you?

    Private Sub AdxOutlookAppEvents1_InspectorActivate(sender As Object, inspector As Object, folderName As String) Handles AdxOutlookAppEvents1.InspectorActivate
        Dim myInsp As Outlook.Inspector, myMailItem As Outlook.MailItem
        myInsp = inspector
        If TypeOf myInsp.CurrentItem Is Outlook.MailItem Then
            myMailItem = myInsp.CurrentItem
            If myMailItem.Sent Then
                Dim theInspector As Outlook.Inspector = TryCast(inspector, Outlook.Inspector)
                If theInspector IsNot Nothing Then
                    Dim selection As Outlook.Selection = Nothing
                    Try
                        selection = theInspector.Application.ActiveExplorer.Selection
                    Catch
                    End Try
                    If selection IsNot Nothing Then
                        ConnectToSelectedItem(selection)
                        Marshal.ReleaseComObject(selection)
                    End If
                End If
            End If
        End If
    End Sub

It calls this procedure properly.

    Public Overrides Sub ProcessBeforeAttachmentRead(ByVal attachment As Object, ByVal e As AddinExpress.MSO.ADXCancelEventArgs)
        Dim myAttachment As Microsoft.Office.Interop.Outlook.Attachment
        myAttachment = attachment
        If Left(myAttachment.DisplayName, 12) = "InstantFile_" Then
            MsgBox("This will open " & myAttachment.DisplayName & " instead of displaying the Note.")
            e.Cancel = True
        End If
    End Sub


The trick was getting a Selection object from the inspector that was passed in to the procedure.
I wound up with
selection = theInspector.Application.ActiveExplorer.Selection  

If you think there's a better way to do this, I'm welcome to suggestions.

Thanks so much -- again -- for your help getting me started on this project.
Posted 30 Oct, 2015 09:55:26 Top
Andrei Smolin


Add-in Express team


Posts: 14106
Joined: 2006-05-11
Hello Gordon,

There is a better way.

Here's a raw sketch of what you need to have in the InspectorActivate event:

Private Sub AdxOutlookAppEvents1_InspectorActivate(sender As Object, inspector As Object, folderName As String) Handles AdxOutlookAppEvents1.InspectorActivate 
    Dim myInsp As Outlook.Inspector = CType(inspector, Outlook.Inspector)
    dim outlookItem as object = myInsp.CurrentItem 
    If TypeOf outlookItem Is Outlook.MailItem Then 
        myMailItem As Outlook.MailItem = CType(outlookItem, Outlook.MailItem)
        If myMailItem.Sent Then 
            ' disconnect from the currently connected item
            ' connect to events of myMailItem
        End If 
    Else
        Marshal.ReleaseComObject(outlookItem)
    End If 
End Sub 


Here's how you handle SelectionChange:

Private Sub AdxOutlookAppEvents1_ExplorerSelectionChange(sender As System.Object, explorer As System.Object) Handles AdxOutlookAppEvents1.ExplorerSelectionChange 
    Dim myExplorer As Outlook.Explorer = CType(explorer , Outlook.Explorer)
    Dim sel as Outlook.Selection
    Try
        sel = myExplorer.Selection
    Catch (ex as Exception)
        'skip the exception which occurs when in certain folders such as RSS Feeds
    End Try
    if sel is Nothing then return
    if sel.Count = 1 then
        dim outlookItem as object = sel.Item(1)
        If TypeOf outlookItem Is Outlook.MailItem Then 
            myMailItem As Outlook.MailItem = CType(outlookItem, Outlook.MailItem)
            If myMailItem.Sent Then 
                ' disconnect from the currently connected item
                ' connect to events of myMailItem
            End If 
        Else
            Marshal.ReleaseComObject(outlookItem)
        End If 
    end if 
    Marshal.ReleaseComObject(sel)
End Sub 


In the same fashion you handle the ExplorerActivate event.

That is, InspectorActivate and ExplorerActivate let you handle this scenario: the user presses Alt+Tab to switch between Outlook windows. Whenever an Outlook window becomes active, your code disconnects from events of the currently connected item and connects to events of the item which is opened (InspectorActivate) or selected (ExplorerActivate). The ExplorerSelectionChange allows you to follow the user selecting another item.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 02 Nov, 2015 07:43:08 Top
Gordon Prince




Posts: 75
Joined: 2015-04-30
Thanks so much.
Posted 02 Nov, 2015 08:47:35 Top
Andrei Smolin


Add-in Express team


Posts: 14106
Joined: 2006-05-11
A small correction:

    if sel is Nothing then return 
    if sel.Count = 1 then 
        dim outlookItem as object = sel.Item(1) 
        If TypeOf outlookItem Is Outlook.MailItem Then  
            myMailItem As Outlook.MailItem = CType(outlookItem, Outlook.MailItem) 
            If myMailItem.Sent Then  
                ' disconnect from the currently connected item 
                ' connect to events of myMailItem 
            Else 
                Marshal.ReleaseComObject(outlookItem) 
            End If  
        Else 
            Marshal.ReleaseComObject(outlookItem) 
        End If  
    end if 


I.e. outlookItem isn't released only if it is a MailItem which has MailItem.Sent=True.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 02 Nov, 2015 09:34:05 Top
Gordon Prince




Posts: 75
Joined: 2015-04-30
Thanks for having one more look at this. I've added the last ELSE segment to my code.

    Private Sub AdxOutlookAppEvents1_InspectorActivate(sender As Object, inspector As Object, folderName As String) Handles AdxOutlookAppEvents1.InspectorActivate
        Dim myInsp As Outlook.Inspector = CType(inspector, Outlook.Inspector)
        Dim outlookItem As Object = myInsp.CurrentItem
        ' Debug.Print("Entered AdxOutlookAppEvents1_InspectorActivate() at " & Now)
        If TypeOf myInsp.CurrentItem Is Outlook.MailItem Then
            Dim myMailItem As Outlook.MailItem = CType(outlookItem, Outlook.MailItem)
            If myMailItem.Sent Then
                ' disconnect from the currently connected item 
                itemEvents.RemoveConnection()
                ' connect to events of myMailItem 
                itemEvents.ConnectTo(myMailItem, True)
            End If
        Else
            Marshal.ReleaseComObject(outlookItem)
        End If
        'Debug.Print("Exiting AdxOutlookAppEvents1_InspectorActivate()")
    End Sub

Upon a bit of reflection, I have a couple of conceptual questions:

1. Should I be connecting to every Outlook event (and/or ReleaseComObject) instead of just Outlook.MailItems? For now, MailItems are the only thing I have that I want to run code on, so I put the If TypeOf test in the code. Would it cause any problem to just connect to every type of item? Does that add any load to running the code? Maybe just connecting to objects the code is going to do something with and ReleaseComObject on everything else makes the most sense.

2. At the top of your last example, there is:

if sel is Nothing then return    
if sel.Count = 1 then   

How do I get "sel" in my code? What's the purpose of this code -- to prevent confusion in the program if the user has >1 item selected in an Explorer? But isn't the code being called with an inspector as its second argument, therefore I know what object I want to work with? So what's the purpose of the
"if sel.Count = 1 then" test?

Cheers.
Posted 03 Nov, 2015 05:10:20 Top
Andrei Smolin


Add-in Express team


Posts: 14106
Joined: 2006-05-11
Gordon Prince writes:
1. Should I be connecting to every Outlook event (and/or ReleaseComObject) instead of just Outlook.MailItems?


outlookItem and myMailItem refer to the same COM object. That is, you can pass outlookItem to itemEvents.ConnectTo(). This allows you to check all sorts of restrictions on all Outlook item types.

Gordon Prince writes:
2. At the top of your last example, there is:


This is a modification of the code given in method AdxOutlookAppEvents1_ExplorerSelectionChange(), see my post marked as "Posted 02 Nov, 2015 07:43:08".

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 03 Nov, 2015 09:00:28 Top