How to build Office COM add-in
in Visual Studio: C#, VB.NET, C++.

Add-in Express™
for Microsoft® Office and .net

Add-in Express Home > Add-in Express for Office and .NET > Online Guide > Tips and notes > COM add-in tips

COM add-in tips

On this page you will find some tips and tricks related to building Office add-ins in Visual Studio related to registering /unregistering the add-in, getting help with COM objects, properties and methods, delays at add-in start-up etc.

Getting help with COM objects, properties and methods

To get assistance with host applications' objects, their properties, and methods as well as help info, use the Object Browser. Go to the VBA environment (in the host application, choose menu Tools | Macro | Visual Basic Editor or just press {Alt+F11}), press {F2}, select the host application in the topmost combo and/or specify a search string in the search combo. Select a class /property /method and press {F1} to get the help topic that relates to the object.

An exception when registering /unregistering the add-in

When your add-in is registered and unregistered, Add-in Express creates an instance of the module. Because in this situation the module isn't loaded by the host application, you can't use any Office-related classes. If the code isn't prepared for this, it will break. If it breaks when you uninstall the add-in, you'll have to clean the registry either manually or using a registry cleaner program.

The same applies to class-level initializers; they are executed even before the module constructor is run.

To initialize your add-in, you need to use the AddinInitialize event of the module. It fires when Office loads the add-in. Note, however, that for Ribbon-enabled Office applications, the first event that the module fires is OnRibbonBeforeCreate.

The add-in doesn't work

If your Office COM add-in does not work, check out: The add-in is not registered, An assembly required by your add-in cannot be loaded, An exception at add-in start-up, and Your add-in has fallen to Disabled Items.

The add-in is not registered

If LoadBehavior is 2, this may be an indication of an unhandled exception at add-in startup. Check Registry keys.

An assembly required by your add-in cannot be loaded

Possible reasons are:

  • the assembly is missing in the installer
  • the user starting the host application doesn't have permissions for the folder where the add-in was installed; say, a per-machine add-in is installed to a user's Application Data folder and another user loads the add-in
  • the PublicKeyToken of your add-in assembly doesn't correspond to the PublicKeyToken mentioned in the Add-in Express loader manifest. See below.

How to find the PublicKeyToken of the add-in

You can find it in the setup project, which must be already built. Click on your add-in primary output in the setup project and, in the Properties window, expand the KeyOutput property and see the PublicKeyToken property value.

An exception at add-in start-up

If an exception occurs in the constructor of the add-in module, or when module-level variables are initialized, Office will interrupt the loading sequence and set LoadBehavior of your add-in to 2. See Registry keys.

Your Office COM add-in has fallen to Disabled Items

If your add-in fires exceptions at startup or causes the host application to crash, the host application (or the end-user) may block the add-in and move it to the Disabled Items list. To find the list, in Office 2000-2003, go to "Help", then "About". At the bottom of the About dialog, there is the Disabled Items button. Check it to see if the add-in is listed there (if so, select it and click Enable). In the Ribbon UI of Office 2007, you find that list on the Add-ins tab of the Office Menu | {host application} Options dialog. In the Ribbon UI of Office 2010 - 2019, the Add-ins tab can be found in the File | Options dialog. After you get the Disabled Items dialog, you select the add-in and click Enable.

Delays at add-in start-up

If you use the WebViewPane layout of your Outlook forms, please check WebViewPane.

Try clearing the DLL cache, see Deploying add-ins - shadow copy.

Quite often it is possible to identify the source of the problem by turning off other COM add-ins and Smart Tags in the host application. If your host application is Excel, turn off all Excel add-ins, too. You can also try turning off your antivirus software.

If your add-in uses .NET Framework 2.0 and adxloader.log (see Loader's log) shows a significant (10 seconds and more) delay between "Creating a new application domain" and "Unwrapping the managed class" stages, there are four possible solutions:

If you have run into a slow-start problem with an Outlook 2013 add-in, see How to avoid "A problem was detected with an add-in".

COM Add-ins dialog

You use this dialog box to turn an add-in on/off. You can also select an add-in to get additional information about the add-in. To open the dialog box, follow the instructions below.

In Office 2000-2003, the COM Add-ins dialog shows only add-ins registered in HKCU. In Office 2007-2013, HKLM-registered add-ins are shown too. See also Locating COM add-ins in the registry.

Office 2000-2003:

  1. Go to the main menu -> Tools -> COM Add-ins

If you don't see the COM Add-ins menu item, go to the main menu -> Tools -> Customize... In the Customize dialog box, select the Commands tab. Click on the Tools entry in the Categories column, then find the COM Add-ins menu item in the Commands column and drag it on a toolbar or the main menu.

Excel 2007, Word 2007, PowerPoint 2007:

  1. Click the Microsoft Office Button
  2. Go to {application name} Options->Add-ins
  3. Select COM Add-ins from the Manage drop-down list at the bottom of the window and click Go.

Outlook 2007:

  1. Go to the Outlook menu -> Tools -> Trust Center -> Add-ins
  2. Select COM Add-ins from the Manage drop-down list at the bottom of the window and click Go.

Office 2010-2013:

  1. Click File -> Options -> Add-ins
  2. Select COM Add-ins from the Manage drop-down list at the bottom of the window and click Go.

What is ProgId?

ProgID - Program Identifier. This is a textual name that represents a server object. It consists of the project name and the class name, like MyServer.MyClass. You find it in ProgIDAttribute of an ADX Module. For instance:


...
'Add-in Express Add-in Module
<GuidAttribute("43F48D82-7C6F-4705-96BB-03859E881E2C"), _
       ProgIdAttribute("MyAddin1.AddinModule")> _
Public Class AddinModule
    Inherits AddinExpress.MSO.ADXAddinModule
...

Here Microsoft describe how you can modify the ProgID:

The format of a ProgID is <Program>.<Component>.<Version>, separated by periods and with no spaces, as in Word.Document.6. The ProgID must comply with the following requirements:

  1. Have no more than 39 characters.
  2. Contain no punctuation (including underscores) except one or more periods.
  3. Not start with a digit.
  4. Be different from the class name of any OLE 1 application, including the OLE 1 version of the same application, if there is one.

Before you modify the ProgId of your add-in project, unregister the project. Failing to do this creates a mess in the registry.

FolderPath Property is missing in Outlook 2000 and XP

The function returns the same value as the MAPIFolder.FolderPath property available in Outlook 2003 and higher.


      Private Function GetFolderPath(ByVal folder As Outlook.MAPIFolder) _
      As String

      Dim path As String = ""
      Dim toBeReleased As Boolean = False
      Dim tempObj As Object = Nothing

      While folder IsNot Nothing
         path = "\" + folder.Name + path
         Try
            tempObj = folder.Parent
         Catch
            'permissions aren't set
            tempObj = Nothing
         Finally
            If toBeReleased Then
               Marshal.ReleaseComObject(folder)
            Else
               'the caller will release the folder passed
               toBeReleased = True
            End If
            folder = Nothing
         End Try

         'The parent of a root folder is of the Outlook.Namespace type
         If TypeOf tempObj Is Outlook.MAPIFolder Then
            folder = CType(tempObj, Outlook.MAPIFolder)
         End If
      End While

      If tempObj IsNot Nothing Then Marshal.ReleaseComObject(tempObj)
      If path <> "" Then path = Mid$(path, 2)
      Return path
      End Function

Word add-ins, command bars, and normal.dot

Word saves changes in the UI to normal.dot: move a toolbar to some other location and its position will be saved to normal.dot when Word quits. The same applies to add-ins: their command bars are saved to this file. See some typical support cases related to Word add-ins and normal.dot below.

  • For reasons of their own, some organizations use read-only normal.dot files. In this case, installing the add-in raises a warning, when Word tries to save normal.dot and finds that it is read-only.
  • The user can set the Prompt to Save Normal Template flag located on the Save tab in the Tools | Options menu and in this way decide whether to save normal.dot or not. This may lead to a mess: some command bars and controls are saved while others are not.
  • Other companies store lots of things in their normal.dot files making them too big in size; saving such files requires extra time.
  • We have had scenarios in which normal.dot is moved or deleted after the add-in is installed; naturally, command bars disappear as well.

You may think that using temporary command bars in these cases is a way out, but this may not be your case, see How command bars and their controls are created and removed? We know the only workaround: don't use normal.dot in a way, which wasn't designed by Microsoft. Normal.dot is a per-user thing. Don't deprive the user of the ability to customize the Word UI. Move all excessive things to other templates. Always insist on clearing the Prompt to Save Normal Template flag. If it is possible, of course...

Custom actions when your COM add-in is uninstalled

When the add-in is being unregistered, the BeforeUninstallControls and AfterUninstallControls events occur. You can use them for, say, removing "hanging" command bars from Word or restoring any other state that should be restored when your add-in is uninstalled.

Visual styles in your forms

Just call System.Windows.Forms.Application.EnableVisualStyles() in your add-in module, say in the AddinInitialize event.

How to develop the modular architecture of your COM and XLL Add-in?

Let's suppose that your COM add-in should conditionally provide (or not provide) some feature: let's call it MyFeature. You could create a class library project, add an ADXAddinAdditionalModule using the Add New Item dialog of your add-in project, and implement the feature.

Then you create a setup project that could, at your choice, either register the assembly using the vsdrpCOM option in the Register parameter of the assembly, or create appropriate keys in HKCU. Note that the former way may require the administrative privileges for the user. Now the class library can write the ProgID of the ADXAddinAdditionalModule into the app.config file of the add-in. When the add-in starts, it can read the app.config, create an ADXAddinAdditionalModuleItem and add it to the Modules collection of the ADXAddinModule class. The best place is the AddinInitialize event of the add-in module. For instance:


Friend WithEvents MyFeature As  _
      AddinExpress.MSO.ADXAddinAdditionalModuleItem

   Private Sub AddinModule_AddinInitialize( _
      ByVal sender As Object, ByVal e As System.EventArgs) _
      Handles Me.AddinInitialize

      Dim MyFeatureProgId As String = System.Configuration. _
         ConfigurationManager.AppSettings("MyFeatureProgId")

      If MyFeatureProgId IsNot Nothing Then
         Me.MyFeature = _
            New AddinExpress.MSO.ADXAddinAdditionalModuleItem(Me.components)
         Me.MyFeature.ModuleProgID = MyFeatureProgId
         Me.Modules.Add(Me.MyFeature)
      End If
   End Sub

If your ADXAddinAdditionalModule contains Ribbon controls, you will need to use the OnRibbonBeforeCreate event of the add-in module.

The same approach is applicable for the Excel XLL add-ins. Just use proper class types in the sample above.

Accessing public members of your COM add-in from another add-in or application

You can always access a public property or method defined in the add-in module via the following path:

HostApp.COMAddins.Item({the ProgID of your add-in}).Object.MyPublicPropertyOrMethod(MyParameter)

The ProgID value above can be found in the ProgID attribute of the add-in module. Note that you access the MyPublicPropertyOrMethod above through late binding - see System.Type.InvokeMember. You can also find a number of samples in this document. And you can search our forums for more samples. See also What is ProgID?

Useful resources

If you didn't find the answer to your questions on this page, please see the HOWTOs section: