Search code examples
c#vstooutlook-addin

Outlook Ribbon Load Inspector.CurrentItem is null


Overview

I have an Outlook add-in created with VSTO. The add-in has a single ribbon (visual designer) for the Mail.Compose ribbon type. The ribbon tab ControlIdType is set to "Custom". The only code in the add-in other than designer code is the following Load handler for the ribbon. this.Context.CurrentItem is unexpectedly returning null.

Code

private void RibbonComposeMail_Load(object sender, RibbonUIEventArgs e)
{
    try
    {
        var inspector = this.Context as Outlook.Inspector;
        if (inspector == null)
        {
            throw new ApplicationException("Fail - Step 1");
        }

        var currentMailItem = inspector.CurrentItem as Outlook.MailItem;
        if (currentMailItem == null)
        {
            throw new ApplicationException("Fail - Step 2");
        }

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Steps

  1. Open draft email. Ribbon loads OK.
  2. Open email from inbox.
  3. Open same draft email. Ribbon fails at step 2, inspector.CurrentItem is null.

Notes

  • I've tested this in Outlook 2007, 2010 and 2013, with an Outlook 2007 and 2010 add-in created in VS2010, and Outlook 2010 add-in created in VS2012. All behave the same.
  • Repeatedly opening the draft email doesn't appear to cause the issue, an Email.Read inspector has to be opened in between.
  • The ribbon tab ControlidType matters. "Custom" will cause the issue, but the default option of "Office" doesn't exhibit the issue.
  • Flipping the scenario on its head and setting the ribbon type to Mail.Read gives the same result, provided the sequence of opening is reversed to Inbox > Draft > Inbox (fail).
  • All possible permutations of calls to Marshal.ReleaseComObject on the inspector and currentMailItem objects makes no difference.

Solution

  • Mikes comments helped reveal to me something a little more curious about the behaviour. At step 1, the RibbonComposeMail_Load event is called once. But at step 3 it is called twice. The first time the event is called at step 3, this.Context.CurrentItem is null, but the second time the event is called, the property holds the email.

    It was comparing item values in the NewInspector event with those in the ribbon Load event which made me notice this. Because the sequence of events at step 3 is: Ribbon_Load, NewInspector, Ribbon_Load. I was getting Ribbon_Load to MessageBox.Show the subject of the mail item in ThisAddIn.CurrentMailItem, but was quite surprised to see it was the subject of the previous email opened, i.e. the inbox email at step 2!

    As it turns out, the solution then is to ignore everything in the Ribbon_Load event if this.Context.CurrentItem is null, because a second Ribbon_Load event is about to be triggered with the correct values set. As to why we see this strange behaviour in step 3 of my example, but not step 1? That's probably a question for the people the implemented the Outlook Object Model.