Interacting with Office functionality in a .NET application can add a new level of functionality while providing the user with familiar methods of getting work done. Explore extending Outlook via a sample add-in.
In my last article on this topic, you learned how to interact with Outlook via your WinForms applications. In this article, you will explore how to extend the functionality of Outlook with your custom code. The business value here is clear: Give your users an environment in which they are comfortable to do tasks specific to their business needs. In addition to reduced training costs for new users, you also gain the benefits of a whole suite of functionality at your fingertips as opposed to the blank canvas. This article will walk through the creation of a simple add-in and will discuss a few tips and tricks to consider when writing your add-ins.
There are some useful Outlook Add-In templates in VSTO (Visual Studio Tools for Office); however, for this demonstration, you will stick with the plain Visual Studio Shared Add-In template. To begin, create a new project of "Shared Add-in" type:
Click here for a larger image.
Follow the wizard. For the "Application Host" section, choose Outlook. Notice here that you can write more generic add-ins to be used in multiple Office applications. For your purposes, you will just stick with Outlook.
Choose your own name and description, and make sure you check the "I would like my Add-in to load when the host application loads" option. You can choose whether or not your add-in should be installed for the current user or all users.
Visual Studio will create a solution with two projects. The first project will hold your add-in functionality. The second is a setup project that builds an MSI file you can use to install your add-in.
Now, you will notice that the first project contains a reference to the Microsoft.Office.Core library, which exposes functionality dealing with command bars, assistants, search, and so forth—basically the elements that are common among the Office applications. At this point, you also want to add a reference to the Outlook Object Library. You can follow the same instructions in the "Getting Started" section of my article "Interacting with Outlook from a WinForms Application." For this example, you will need to add one more reference to the System.Windows.Forms .NET library. The following uses directives in the Connect.cs file, which VS provides, and will make your code less verbose:
using Outlook = Microsoft.Office.Interop.Outlook;
Notice you will be using System.Reflection. Optional arguments permeate COM. The way around optional arguments in C# is to use the System.Reflection.Missing type, as you will see later in the code.
Creating Your First Outlook Add-In
The Connect class is the "in" for our add-in. It implements the Extensibility.IDTExtensibility2 interface. The required methods are stubbed out for you. The methods of interest for the purpose of this article are OnConnection and OnStartupComplete. You will use the OnConnection method to set up your class-level variables. The template provides two of these variables:
private object applicationObject;
private object addInInstance;
Because you know you will be dealing with only Outlook, the first thing to do is change the type of the applicationObject from object to Outlook.Application. You also will change the assignment provided in the OnConnection method to appropriately cast the object:
applicationObject = (Outlook.Application)application;
You also want to keep class-level references to the active explorer and its command bars, as well as the button you will create and its caption (see the later Tips section for more details):
private Outlook.Explorer activeExplorer;
private CommandBars commandBars;
private CommandBarButton buttonCheckContacts;
private string buttonCheckContactsCaption = "Check Contacts";
You will assign the first two references in the OnConnection method as well:
activeExplorer = applicationObject.ActiveExplorer();
commandBars = activeExplorer.CommandBars;
The OnConnection method will be called every time Outlook opens. Once Outlook is finished loading, the OnStartupComplete method is called. You will use this opportunity to first check if your button has been created, and if it has not, you will do so:
//create a button on the main toolbar if it doesn't already exist
buttonCheckContacts = (CommandBarButton)commandBars
buttonCheckContacts = (CommandBarButton)commandBars
Missing.Value, Missing.Value, Missing.Value, Missing.Value);
buttonCheckContacts.Caption = buttonCheckContactsCaption;
buttonCheckContacts.OnAction = "!<TestAddin.Connect>";
You use the commandBars reference to pull out the "Standard" command bar, which is the toolbar located just under the main menu bar in Outlook. This is where you want to add your button. Command bar buttons are indexed by their captions. If you cannot find the button on the standard toolbar, you will create it and set its caption property to the name you want the button to display (declared earlier). You will also set the OnAction property to point to the ProgId of this class (formatted like "!<ProgID>"). You can find the ProgId in a class attribute. Note that yours might differ depending on the name you chose for your solution:
public class Connect : Object, Extensibility.IDTExtensibility2
Finally, whether the button was already created or not, you will hook up an event handler for the button click event:
buttonCheckContacts.Click += new
All that is left to do is decide what you want to happen when the user clicks the button. For this example, you will return a message box listing the names of employees in the user's contacts list who have anniversaries in the next two weeks. Most of the functionality in the event handler has already been covered in Part One of this article series, but I will note a couple of things of interest here. Firstly, you will use the GetDefaultFolder method of Outlook.Namespace class instead of the PickFolder method employed earlier so that the user is not prompted with a folder picker dialog. Secondly, you feed a more advanced filter to the Outlook.MAPIFolder.Items.Restrict method to get results quickly (as opposed to looping through the entire contacts list to find the items that fit our description, which can be a lengthy process):
DateTime endRange = DateTime.Now.AddDays(14);
string filter = "[MessageClass] = \"IPM.Contact\"
AND [Anniversary] >= '" +
"' AND [Anniversary] <= '" +
endRange.ToShortDateString() + "'";
As in Part One, if you need some further elaboration on writing filter strings, take a look at the MSDN article.
Building, Installing, and Testing Your Add-In
First, build your main project. You then can build the setup project to create an MSI file. You either can run the resulting file to install your add-in, or right-click on the project in Solution Explorer and choose Install. Installing the add-in will register your add-in for COM so that Outlook recognizes it. You can perform a search for regasm if you want more information on registering for COM, but that topic is outside the scope of this article. Close and re-open Outlook, and you will see your new button on the toolbar. Click the button and test its functionality; don't forget to add a few contacts with anniversaries in the appropriate range. After you initially install your add-in (register it), to see changes in your add-in on your development machine you will only need to rebuild your project. It does not require you to uninstall and re-install the add-in. Note that you will need to close Outlook before building or you will get an error stating that the process is in use.
Tips for Working with Outlook Add-Ins
In my experience, Outlook add-ins can be difficult to create and debug. In one of my projects, we used an Outlook add-in to "push" emails from Outlook into our application as attachments for evidence in a project. When working with some of the legacy code, I have had to discover the hard way some of the idiosyncrasies of writing an add-in. Here are a few things I have learned in the process:
- Keep class level references to objects you need to reuse; otherwise, you may notice a problem with dead menus and buttons because of garbage collection. These types of bugs are difficult to trace because objects used with COM interop may not be collected when you expect them to be.
- Because of the issue above as well as others, test your add-in on different machines for as long of a time period as possible. Bugs that may never show up in your development environment can manifest themselves in other, even slightly different, machines.
- If your add-in stops working for no apparent reason, check the disabled add-in list. When something goes wrong with any add-in (possibly not even yours), Outlook may decide to disable all add-ins. You can find this list in Help About Disabled Items.
- If all else fails, delete and re-create your menus or buttons on startup to clean up any funniness lurking in Outlook. This will give your add-in a fresh start when Outlook opens and could clear up some of the odd behavior. Unless your add-in takes a lengthy amount of time to set up, you should not notice much of a difference in performance.
Part One of this series introduced you to Outlook interaction from within your WinForms applications. In this article, you learned that a well-written Outlook add-in can delight your users with just that little extra functionality they need to do their jobs easier and better. Microsoft Office is a powerful suite that helps business users all over the world to manage their day-to-day functions; why not take advantage of the well-tested, widely used pre-existing applications to jumpstart your own development? This article has introduced you to the world of add-ins through a simple Outlook sample, and I hope that it has given you the tools (and the drive) to begin discovering ways you can create innovative and highly-valued extensions to the Office environment.
Download the Code
You can download the code that accompanies this article here.
I would like to thank Matt Goebel for his suggestions and help with this article series.
About the Author
Rachel Wireman (MCPD, MCTS) is a developer specializing in Windows-based solutions at Crowe Chizek in Oak Brook, Illinois. Reach her at email@example.com.