Creating an Outlook Add-In Part 1

by Hannes du Preez

Learn how to crate an Outlook Add-in to backup Important Email. Part 1 of this article concentrates on Outlook 2003and VB.NET 2003. Part 2 will concentrate on Outlook 2007 & Outlook 2010 with VB 2010.


Add-Ins are custom programs that helps extend the capabilities of a certain program. For example, we can create add-ins to make Outlook, or any other Office product more powerful. We can add cool features to existing programs. With this article series we will create Outlook Add-Ins to backup our important emails. This article ( Part 1 ), will concentrate on Outlook 2003 and VB.NET 2003, and Part 2 will concentrate on Outlook 2007 & Outlook 2010 with VB 2010.

Our Add-In's Purpose

I made this add-in to save some of the very funny emails I receive, and I receive a lot. This add-in ( called FunnySave ) will allow us to browse an outlook folder, which contains all of the email we want to backup ( this can be any email ), then save them all to disk. Short and sweet; supposedly. We have to do a lot of work, to make sure we get the right emails as well as to save them in the proper format. Without any further ado, let us get started.

Outlook 2003 Setup

This step is optional, if you have a separate folder containing all the email you want to backup already, or you do not want to do it. I have a folder named Funnies Limbo inside Outlook, specifically to store my funny emails. It looks like the following picture:

Shared Add-In
Figure 1 - Funnies Limbo

Design & Code

With Add-Ins, we don't have to design forms, everything is code based. You may be wondering how are we going to create something like a BrowseForFolder dialog, or even a button. With code, only with code, as you will see shortly.

Open Visual Studio 2003, and click on File, New, Project, Shared Add, under Other Project Types, Extensibility Projects, as shown in the next picture:

Funnies Limbo
Figure 2: Shared Add-In

This will open the Shared Add-In Wizard; let us look at the steps screen for screen.

Screen 1
Figure 3: Screen 1

Screen 1 just provides some basic information about what is going to happen.

Screen 2, Language Options
Figure 4: Screen 2, Language Options

On the second screen we must choose which language we will use for this Add-In. Choose Visual Basic.

Screen 3, Select Host Application
Figure 5: Screen 3, Select Host Application

In this screen we must select Microsoft Outlook as the application this Add-In is for.

Screen 4, Add-In details
Figure 6: Screen 4, Add-In details

Fill in the text fields according to the above picture.

Screen 5, Add-In Options
Figure 7: Screen 5, Add-In Options

A very important thing to remember here, is the bottom checkbox. We must remember that if we do not choose this, only one user can use it, and not all the users on one computer. When creating the setup application, we must keep this in mind.

Figure 8: Summary

Once we have clicked Finish, Visual Studio will create the project according to our specifications. Your Solution Explorer will look similar to the following picture.

Solution Explorer
Figure 9: Solution Explorer

You will notice that it only gives us two things, namely: AssemblyInfo and Connect. AssemblyInfo is where we enter the details of who wrote the program, what version it is, etc. Connect is very important. This is where we will write our code to Connect to Outlook. When you open Connect.vb in Code View, you will notice that VS was nice enough to put some basic functionality inside. The namespaces were added automatically, and some of the Add-In's events were also put in, so that we know where to put the code to make our Add-In work.

If you haven't done so already, open Connect.vb in Code View. You can do this by clicking on the View Code button, or by right clicking and selecting View Code. Make sure that the following Namespaces are there:

Imports Microsoft.Office.Core 'Core Framework
Imports Extensibility 'Ability to Extend Office
Imports System.Runtime.InteropServices 'Interop Services

If you look closely, you will see some gibberish code above your class declaration.

'GUID and Product Info
<GuidAttribute("2B858370-EBE4-497C-B9C3-A554C60F1AA5"), ProgIdAttribute("FunnySave.Connect")> _
Public Class Connect 'Connect to Office Application

    Implements Extensibility.IDTExtensibility2

The line above the Class declaration gives our Add-In a unique Identifier on the system. GUID means Globally Unique Identifier. Each object on your system has one. The ProgIdAttribute part identifies which program will connect to Outlook, in this case it will be FunnySave. The Connect class also implements Extensibility.IDTExtensibility2. This hosts the events that always occur in add ins. We will work with these events during the course of building our Add In.

Let us continue adding our own code to give our Add In some functionality, apart form the skeleton it provided us.

Add the following three variables underneath the Implements line:

    Private objAppObject As Object 'Application Object
    Private objAddIn As Object 'Instance

    Private WithEvents btnFunny As CommandBarButton 'Our Command Button

Here we made our main Application object, and add in object. We will also need a button. This button will make everything happen.

I think it is best to start with the Add-Ins events supplied by the IDTExtensibility2 interface, and then continue to give our button the functionality it needs.


This event is similar to a Form_Load event, if you get what I'm trying to say. It means that the Add in has been loaded. Our event looks like this:

    '''Outlook Finished Loading into Memory
    Public Sub OnStartupComplete(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnStartupComplete

        Dim cbCommandBars As CommandBars 'Outlook Toolbars

        Dim cbAdvancedBar As CommandBar 'Advanced Toolbar

        cbCommandBars = objAppObject.CommandBars 'Get Command Bars

        If cbCommandBars Is Nothing Then 'If None

            'CommandBars Collection on Explorer object.
            cbCommandBars = objAppObject.ActiveExplorer.CommandBars

        End If

        cbAdvancedBar = cbCommandBars.Item("Advanced") 'If Advanced Toolbar is Shown, cbAdvancedBar is it then.

        'If Our Button has noot been Deleted, Use Exiting One.
        btnFunny = cbAdvancedBar.Controls.Item("Save Your Funnies")

        If btnFunny Is Nothing Then 'If Our Button doesn't Exist

            btnFunny = cbAdvancedBar.Controls.Add(1) 'Add Our Button to the Advanced Outlook Toolbar

            With btnFunny 'Set Our Button's Properties

                .Caption = "Save Your Funnies" 'Caption
                .Style = MsoButtonStyle.msoButtonIconAndCaption 'Style
                .TooltipText = "Save Your Funnies" 'Tooltip Text
                .FaceId = 1087 'Picture

                .Tag = "Save Your Funnies" 'Tag

                'OnAction is Optional, but Recommended. 
                'It should be Set to the ProgID of our Add-In, so that if
                'the Add-in has not been Loaded when We Click it,
                'MSO loads the Add-In Automatically and raises
                'the Click Event for the Add-In to handle. 
                .OnAction = "!<MyCOMAddin.Connect>"

                .Visible = True 'Visible

            End With

        End If

        cbAdvancedBar = Nothing 'Release Advanced Bar Object
        cbCommandBars = Nothing 'Release Command Bars Object

    End Sub

We create our button, with custom properties here. We also indicate where we want this button to be displayed - it must be connected to an Outlook toolbar - in this case, it resides on the Advanced toolbar. An interesting thing to note here is the picture of the button. Outlook does provide some code numbers for buttons, but if you want to make your image and connect it to the button, that is a totally different animal, as you will see in part 2 of this series.


This event fires when the application that hosts the Add-In closes. Our code for this event looks like:

    '''Begin Unloading Outlook
    Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown

        btnFunny.Delete() 'Remove Our Button
        btnFunny = Nothing 'Release Object
        objAppObject = Nothing 'Remove Object References
    End Sub

Very straightforward. We delete the button from the toolbar and set all our objects to Nothing, otherwise they will remain in memory, even after the host application is out of memory.


The connection with the Add-In is made. Enter the following code:

    ''' Connection to Our Add In
    Public Sub OnConnection(ByVal objAppOutlook As Object, ByVal cmConnectionMode As Extensibility.ext_ConnectMode, ByVal objAddIn As Object, ByRef arrExtEvent As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection

        objAppObject = objAppOutlook 'We Are Now Connected
        objAddIn = objAddIn 'Current Instance

        'Call OnStartupComplete
        If (cmConnectionMode <> Extensibility.ext_ConnectMode.ext_cm_Startup) Then _
           Call OnStartupComplete(arrExtEvent)

    End Sub

This event calls the OnStartupComplete event once we are sure the connections have been made


This occurs when the Add-In is unloaded form its host. Our event must look like:

    ''' Disconnection from Our Add In
    Public Sub OnDisconnection(ByVal dcmDisconnectionMode As Extensibility.ext_DisconnectMode, ByRef arrExtEvent As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection

        If dcmDisconnectionMode <> Extensibility.ext_DisconnectMode.ext_dm_HostShutdown Then _
                  Call OnBeginShutdown(arrExtEvent) 'Is the System Shutting Down?

        objAppObject = Nothing 'Remove Application Object

        If dcmDisconnectionMode = ext_DisconnectMode.ext_dm_UserClosed Then
            Call OnBeginShutdown(arrExtEvent) 'Has the User Closed Outlook?

            objAppObject = Nothing 'Remove Application Object

        End If
    End Sub

Here, we must determine what caused the Shutdown of the host application. Was it closed by the user, or was it because of a system shutdown.


This method is most often used to enforce dependencies on other add-ins. That is, if an add-in requires the presence of another add-in (or other program) before it can run properly, you can check the status with this method. Ours will be empty because we are not dealing with any other dependencies, but let us still put it in:

    Private Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
    End Sub

Now all the events needed for this Add In to work are in there, we need to make our button work. If you can recall, we want our button to save or backup emails. To do this, we need two subs and two functions. Let us concentrate on the Subs


This sub procedure is the main procedure that will be called by btnFunny. Its main purpose will be to loop through all the selected folders and subfolders, to obtain all the emails, format the emails properly, and then of course, save them. Add the next sub:

    '''Main Sub to Backup All Emails 
    Sub BackupEmails()

        Dim i As Long 'First Loop - Folders
        Dim j As Long 'Second Loop - Subfolders
        Dim lngRemoveSlash As Long 'Name, After Unecessary \ Was Removed

        Dim strSubject As String 'Email Subject
        Dim strEmailName As String 'Email Name
        Dim strFileName As String 'Filename of Email
        Dim strPath As String 'Path
        Dim strSelFolder As String 'Selected Outlook Folder
        Dim strSelFolderPath As String 'Selected Outlook Folder Path
        Dim strSaveToFolder As String 'Where to Save to

        Dim outNameSpace As Outlook.NameSpace 'Outlook Namespace
        Dim objApp As Outlook.Application 'Outlook Application
        Dim objMailFolder As Outlook.MAPIFolder 'Outlook Mail Folder
        Dim objMailItem As Outlook.MailItem 'Outlook Email Item

        Dim objFSO As Object 'File System Object
        Dim objFolderToBackup As Object 'Which Folder Must We Backup

        Dim colFolders As New Collection 'All Folders
        Dim colEntryID As New Collection 'All Entities
        Dim colStoreID As New Collection 'All Stores

        objFSO = CreateObject("Scripting.FileSystemObject") 'Create FSO Object

        objApp = New Outlook.Application 'Create Outlook Instance
        outNameSpace = objApp.GetNamespace("MAPI") 'Get Appropriate Outlook Namespace

        objFolderToBackup = outNameSpace.PickFolder 'Choose Folder to Backup

        If objFolderToBackup Is Nothing Then 'Nothing Selected

            Exit Sub

        End If

        strPath = CustomBrowseForFolder() 'Show & Get Output Folder

        If strPath = "" Then 'If No Path Chosen

            Exit Sub

        End If

        If Not Right(strPath, 1) = "\" Then 'Add \ Afterwards

            strPath = strPath & "\"

        End If

        Call GetOutLookFolders(colFolders, colEntryID, colStoreID, objFolderToBackup) 'Get All Folders

        For i = 1 To colFolders.Count 'Loop Through Folders

            strSelFolder = StripCharacters(colFolders(i)) 'Remove Characters that aren't Allowed in Filenames

            lngRemoveSlash = InStr(3, strSelFolder, "\") + 1 'Remove \

            strSelFolder = Mid(strSelFolder, lngRemoveSlash, 256) 'Edited Filename
            strSelFolderPath = strPath & strSelFolder & "\" 'Add \

            strSaveToFolder = Left(strSelFolderPath, Len(strSelFolderPath) - 1) & "\" 'Get Parent Folder of Message

            If Not objFSO.FolderExists(strSelFolderPath) Then 'If Folder doesn't Exist, Create it


            End If

            objMailFolder = objApp.Session.GetFolderFromID(colEntryID(i), colStoreID(i)) 'Get All Subfolders in Chosen Folder

            For j = 1 To objMailFolder.Items.Count 'Establish Count

                objMailItem = objFolderToBackup.Items(j) 'Get Subfolder Items, ie, Emails in Folder

                strSubject = objMailItem.Subject 'Get Subject
                strEmailName = StripCharacters(strSubject) 'Strip Invalid Characters out of FileName

                strFileName = strSaveToFolder & strEmailName & ".msg" 'Name of Message to be Saved

                strFileName = Left(strFileName, 256)

                objMailItem.SaveAs(strFileName, 3) 'Save

            Next j

        Next i

    End Sub

That was a mammoth chunk of code! The functionality of this sub is very simple actually.  We first identify the folders and emails for backup via the GetOutLookFolders sub. Then, we format the message names properly. This means that we get rid of characters that aren't allowed in filenames via the StripCharacters function and some further string manipulation. if you are fairly new to string manipulation, check out this FAQ. Lastly, we save the emails. For this we need the CustomBrowseForFolder function, which produces a BrowseForFolder dialog.


The second sub looks like:

    '''Get All Outlook Folders
    Sub GetOutLookFolders(ByVal colAllFolders As Collection, ByVal colAllEntryIDs As Collection, ByVal colAllStoreIDs As Collection, ByVal strSelFolder As Outlook.MAPIFolder)

        Dim strSubFolder As Outlook.MAPIFolder 'Get Chosen Folder

        colAllFolders.Add(strSelFolder.FolderPath) 'Path
        colAllEntryIDs.Add(strSelFolder.EntryID) 'Entry ID
        colAllStoreIDs.Add(strSelFolder.StoreID) 'Store ID

        For Each strSubFolder In strSelFolder.Folders 'Loop Through Folders

            GetOutLookFolders(colAllFolders, colAllEntryIDs, colAllStoreIDs, strSelFolder) 'Get Subfolders

        Next strSubFolder

        strSubFolder = Nothing 'Release Object

    End Sub

As I mentioned, this sub loops through our wanted folder and all its subfolders. Now on to the Functions.


By its name, it should be pretty obvious to you that we are making a Browse For Folder dialog, here is the code:

    '''Display Browse for Folder Dialog
    Function CustomBrowseForFolder(Optional ByVal strDefaultLoc As String = "C:\Documents and Settings\hannes\Desktop\To Backup") As String

        Dim objShell As Object 'Shell Object

        objShell = CreateObject("Shell.Application"). _
        CustomBrowseForFolder(0, "Please Choose a Folder to Backup", 0, strDefaultLoc) 'Create BFF Dialog

        CustomBrowseForFolder = objShell.self.Path 'Set Initial Path

        objShell = Nothing 'Release Object

    End Function

In order to call the Browse For Folder dialog, we need the Shell object. We then specify its title and initial directory, that is it.


This one is tricky. StripCharacters makes use of Regular Expressions to filter out unwanted characters. As I mentioned, Windows is very strict with filenames, and there are certain characters, which might appear in your emails' titles that are not allowed. This is why we need to do this. The code follows:

    '''Strip Invalid Characters from Subjects
    Function StripCharacters(ByVal strSubs As String) As String

        Dim objRegEx As Object 'Regular Expression Object

        objRegEx = CreateObject("vbscript.regexp") 'Create Regular Expression Object

        'Regex Pattern to Identify Illegal Characters
        objRegEx.Pattern = "[\" & Chr(34) & "\!\@\#\$\%\^\&\*\(\)\=\+\|\[\]\{\}\`\'\;\:\<\>\?\/\,]"

        objRegEx.IgnoreCase = True 'Ignore Case
        objRegEx.[Global] = True

        StripCharacters = objRegEx.Replace(strSubs, "") 'Replace Illegal Character with Empty String

        objRegEx = Nothing 'Release Reg Ex Object

    End Function

The pattern is of importance here, feel free to add more filter characters in there.

We can build our DLL now by choosing Build Solution from Visual Studio's Build menu. There should be no errors. If you do encounter any errors, make sure you have written all the code as it is in this article. I am providing a working sample, in any case - if you are really battling to get it working.

Setup & Installation

The final piece of the puzzle we need to make this Add In work, is to create a Setup Application. The Setup is actually the most important step. The reason why I say so is that it not only installs the Add In, but it registers all the components for this Add In, so that it can work, without any hassles.

Add a Setup Project to your project, by clicking File, Add Project, New Project. Under Other Projects, select Setup.

This will add it to your project. You should see it in your Solution Explorer.  Right click your setup project in the Solution Explorer and choose Add, File, Primary Output and select your project when prompted. All the necessary files to make the Add In work, have been added. Build your Setup project. There should be no errors. If there are, make sure you did not miss a step. I am including a working Setup application for this Add In, in this article. After the Build was successful, right click your Setup project again, and choose Install. This installs your Add In.

Obviously, you can run the Setup from outside the Visual Studio IDE as well. When you launch Microsoft Outlook, and have the Advanced toolbar visible, you will see a button similar to the following picture:

Figure 10: Save Your Funnies button

Click on it and select a folder to backup. Choose a location to backup to, and click OK.  Outlook will pop a box asking you permission to save. It is the only annoyance in there, but you can set a time limit ( for which to allow this application to run ) in this box.


I hope my article was useful, and that you have enjoyed and learned something from it. Stay tuned for Part 2, which will cover Outlook 2007 and Visual Basic 2010. Until next time, cheers!

This article was originally published on Monday Aug 29th 2011
Mobile Site | Full Site