Converting existing Office COM add-in projects to Add-in Express
Last week I had a chance to check out how easy the conversion process is.
A customer related about troubles he was having when trying to get his Outlook add-ins to work. Soon it became clear that this is yet another case of a VSTO add-in colliding with Microsoft Dynamics CRM Outlook add-in (see also When Outlook add-ins collide: things far-fetched and real).
Because the use of the VSTO edition of Add-in Express doesn’t make your VSTO add-in a non-VSTO add-in, this edition couldn’t prevent the collision. I suggested using the .NET edition that provides a loader of its own (see Shims in Add-in Express projects).
For the customer to test if Add-in Express for Office and .NET based add-ins work with the MS CRM add-in, I created a sample Outlook COM add-in demonstrating basic Add-in Express features: command bars in Outlook Explorer and Inspector windows and Ribbon controls in Outlook 2007 Inspector windows. When the add-in was recognized as working (it couldn’t be the other way!), the customer sent me a part of its real Outlook 2003 add-in project developed in VS 2008 and asked me to convert it to Add-in Express 2008 for .NET.
Both Add-in Express add-ins and VSTO-based ones have a class that is the add-in itself: in this class you create command bar and ribbon controls, handle events, etc. In VSTO, the class is ThisAddin; in Add-in Express the class is ADXAddinModule, or the add-in module. Unlike VSTO, Add-in Express supplies a designer for the add-in module. The designer allows adding Add-in Express components such as Outlook Explorer CommandBar, Ribbon Tab, etc. Naturally, you can use the designer to house any components.
In addition, you can specify the add-in module properties such as add-in name, description, load behavior. Add-in Express provides an Outlook-specific property page that you can add to your project; being mentioned in appropriate properties of the add-in module and supplied with a title, such a page gets displayed in the Tools | Options and FolderProperties dialog.
The VSTO add-in written by the customer contained command bar buttons only. You can see the most essential part of its code below:
private void newExplorer_Event(Outlook.Explorer new_Explorer) { ((Outlook._Explorer)new_Explorer).Activate(); myToolbar = null; AddToolbar(); } private void AddToolbar() { if (myToolbar == null) { Office.CommandBars cmdBars = this.Application.ActiveExplorer().CommandBars; myToolbar = cmdBars.Add ("myToolbar", Office.MsoBarPosition.msoBarTop, false, true); } try { loginButton = (Office.CommandBarButton)ctiToolbar.Controls.Add (1, missing, missing, missing, missing); loginButton.Style = Office.MsoButtonStyle.msoButtonIconAndCaption; loginButton.TooltipText = "Press to Login"; loginButton.Tag = "Login"; loginButton.FaceId = 277; loginButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(LoginClick); myToolbar.Visible = true; } catch (Exception error) { MessageBox.Show ("Error loading the toolbar:" + error.Message, "Error"); } }
The conversion tactics that I chose was to create an Add-in Express equivalent for every command bar button (there were quite a lot of them), set their properties according to the VSTO add-in code, copy event handlers, and then compile the project dealing with each compile error separately.
I started with adding the Explorer CommandBar component to the add-in module and setting its properties:
In the screenshot above, you see a number of properties that you usually set in your code to create an appropriate command bar. Note that you need to specify two names: for the component itself and for the command bar created in Outlook. Pay attention to the FolderName(s) and ItemTypes properties: they make your command bar context-sensitive! Say, the properties above are set so that the command bar is displayed whenever the user navigates to an Outlook folder the default item type for which is mail. Another property that requires some explanation is UseForRibbon. This property exists in all Add-in Express command bar components; when it is true, the command bar is created in Ribbon-enabled Office applications. In the above screenshot, this property is set to show the command bar in Outlook 2007.
The Controls property provides a visual designer, which allows creating command bar controls at design-time. So I added a button and set its properties:
The property that might have caught your attention is the ControlTag property. It demonstrates the way Add-in Express identifies command bar controls: it writes a GUID to the Tag property of the actual command bar control and provides the Tag property that the developer can use for their own needs.
Besides allowing you to do many things visually, which otherwise you will need to set in your code, the button component also provides the context sensitivity options: OlExplorerItemTypes, OlInspectorItemTypes, and OlItemTypeAction properties allow you to enable or hide/show this toolbar button.
The settings above generate the following code in the InitializeComponent method of the add-in module:
private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.adxOlExplorerCommandBar1 = new AddinExpress.MSO.ADXOlExplorerCommandBar(this.components); this.loginButton = new AddinExpress.MSO.ADXCommandBarButton(this.components); // // adxOlExplorerCommandBar1 // this.adxOlExplorerCommandBar1.CommandBarName = "adxOlExplorerCommandBar1"; this.adxOlExplorerCommandBar1.CommandBarTag = "c5066dad-b93f-4631-8534-7281566b2d94"; this.adxOlExplorerCommandBar1.Controls.Add(this.loginButton); this.adxOlExplorerCommandBar1.Temporary = true; // // loginButton // this.loginButton.Caption = "Press to Login"; this.loginButton.ControlTag = "fc9237cd-4dae-4bec-9702-3e6282c2c0e3"; this.loginButton.FaceID = 277; this.loginButton.ImageTransparentColor = System.Drawing.Color.Transparent; this.loginButton.Style = AddinExpress.MSO.ADXMsoButtonStyle.adxMsoButtonIconAndCaption; this.loginButton.Tag = "Login"; this.loginButton.Temporary = true; this.loginButton.TooltipText = "Press to Login"; this.loginButton.Click += new AddinExpress.MSO.ADXClick_EventHandler(this.loginButton_Click); // // AddinModule // this.AddinName = "MyAddin1"; this.SupportedApps = AddinExpress.MSO.ADXOfficeHostApp.ohaOutlook; this.AddinInitialize += new AddinExpress.MSO.ADXEvents_EventHandler (this.AddinModule_AddinInitialize); }
When looking at this, you must ask the main question: Does Add-in Express deserve good words that you can find over the web?
Of course, it does! The obvious bug revealing itself only when an Outlook add-in written in VSTO is run together with the Microsoft Dynamics CRM 3.0 addin will be fixed sooner or later (in my blog post on colliding Outlook add-ins I mentioned a hotfix for the same problem with version 4.0 of the same Outlook add-in). Besides that, besides the approach that allows you to bypass MANY problems with Office command bars and controls, besides the fact that the add-in created with Add-in Express will work in all Outlook versions, and even besides the possibility to use components creating the Ribbon UI of your add-in in the same project… Besides all this, Add-in Express allows deploying your Office add-ins easily because it provides ready-to-use custom actions integrated in the development process so that you don’t need even to think about whatever registry keys, security settings and such. Add to this the ability to deploy your add-in supporting Office 2000-2007 via ClickOnce (wow! ).
So Add-in Express isn’t just a set of controls, it is a technology targeted to minimize your efforts when creating the UI of your add-in and when deploying it. What is left to you is to write the business logics of your add-in.
Andrei Smolin
Add-in Express Team Leader