Troubleshooting Outlook Form Regions

Recently I had to debug a strange issue with an Outlook VSTO plugin where the plugin would install smoothly and load correctly but my custom calendar region was not showing as expected.  To complicate matters a little further, I had some clients on 32-bit and some on 64-bit desktop systems so it was not a straightforward install.

You can find the base steps for registering a VSTO add-in here.

Note: An easy check to see if your add-in is automatically loading correctly is to verify that the LoadBehavior key stays at 3.  You can keep the registry open while you load your Office application and refresh to see if it was unloaded.

Outlook Form Regions have an extra step though and depending on the desktop architecture you are on, you’ll need to create the following registry keys as well.

x32

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Outlook\FormRegions\IPM.Appointment]
"MySuperOutlookPlugin.Plugins.MyCalendarRegion"="=MySuperOutlookPlugin.Plugins"

x64

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\FormRegions\IPM.Appointment]
"MySuperOutlookPlugin.Plugins.MyCalendarRegion"="=MySuperOutlookPlugin.Plugins"

Where these values equal,

MySuperOutlookPlugin.Plugins.MyCalendarRegion – is the fully qualified name of your VSTO assembly and class name of the Outlook Region file.

=MySuperOutlookPlugin.Plugins – is the name of your assembly.

Once you have done this, restart Outlook and you will now see the your Outlook Region load appropriately.

VSTO – Enabling Ribbon Controls at RunTime

I recently ran into an issue where I needed to enable and disable Ribbon controls in a VSTO plugin where the Ribbon controls were initialized through a Ribbon.xml file.

This can be a bit challenging s the controls in the Ribbon XML file are not available to your code at design time when you are trying to write the actual code.

In addition, I needed to trigger the decision handling logic from another section of code not associated to the Ribbon.

Accomplishing this task involved a number of steps and was done building an integration to Outlook (not sure if this would be similar in Word or Excel).

Identify the controls at run-time

In each control that I wanted to control the state on, at the time of the Ribbon’s instantiation I had them call the “getEnabled” property which called a function that enabled them all and stored an instance of that control in memory for later use.

<labelControl id="lblMyLabel" label="This is My Text" getEnabled="setState" />

In code, I then had a simple List<IRibbonControl> collection created that stored this information.

Note: If you are dynamically adding controls at runtime this could be complex.

Implementing Decision Logic

I won’t go too deep here as every application has their own applicable set of logic but for me a simple eventing framework where I could Fire a State change from any part of my application and subsequently have my ribbon handler listen on the event at start worked perfectly for me.

Changing State

In my aforementioned event, the control determined when to fire a state changed event and thereby would send to the whether the Ribbon should be enabled or disabled.

When receiving the event, it was a simple matter of invalidating the current control on the ribbon and calling the initial state handler that was tied to be ribbon control to reset it’s enabled or disabled status.

foreach (IRibbonControl ctl in _controls)
{
ribbon.InvalidateControl(ctl.Id);
setState(ctl);
}

In doing this, I had 5 controls as part of ribbon – textboxes, labels, buttons and checkboxes and they all worked perfectly.

This was a little more roundabout than I would have liked but I’m happy with the results and consistent implementation.  If I decide to add new controls to my ribbon, all I need to do is ensure the getEnabled property is subscribed to and the state handler will take care of the rest.

 

Retrieving Email Addresses in Outlook

Sometimes it seems that what we thought was the easiest problem to solve actually turns out taking the longest amount of time to figure out.

Case in point – finding the email address of the currently logged in user running Outlook in a VSTO plugin.

If you are looking to do this, see below and let the code set you free.

Recipient CurrentUser = this.Application.Session.CurrentUser;

CurrentUser.AddressEntry.GetExchangeUser().PrimarySmtpAddress.ToString()

A little longer and less direct than I would have thought (i.e., at this stage, my user is not a recipient to anything) but the reasoning becomes a little more apparent if I am trying to find the email addresses on a set of recipients on either an appointment or mail message.

.Recipients[1].AddressEntry.GetExchangeUser().PrimarySmtpAddress.ToString()

Creating a custom Tab in VSTO

If you haven’t used VSTO, it’s the framework for developing Office Integrations.  Yes, people are still developing Office plugins, although Flow is coming on strong, there is still a need for organizations to have components directly embedded in their primary applications of choice.

If you’re looking to get started on building your own Tab in Office you can do this very easily by adding a Ribbon.xml file to your VSTO project with the following syntax.

<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
 <ribbon>
 <tabs>
 <!--<tab idMso="TabMail">-->
 <tab id="tabForgotten" label="Coder">
 <group id="MyGroup" label="Content">
 <button id="btnGo" label="Connect" 
 screentip="Go" onAction="OnConnectClicked"
 supertip="Go to start."/>
 </group>
 </tab>
 </tabs>
 </ribbon>
</customUI>

Once you’ve added that snippet, simply navigate back to your main AddIn.cs file and instantiate your ribbon.

protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new SuperRibbon();
}

Compile and run (in this example, I created an Outlook VSTO plugin) and you can now see your new menu item.

Capture

Connecting the events are even easier as a complimentary .cs file is created where you can easily wire up this event.

public void OnConnectClicked(Office.IRibbonControl control)
{

System.Diagnostics.Debug.WriteLine("HERE");
}

Lastly, you’ll notice that in my XML tab declaration there is a value that is commented out called TabMail.  All built-in Tabs have their own tabs that you can piggy back off to include your controls therein instead of creating your own tab as was done previously.  All that needs to change is that value.