Creating an Outlook My.Blogs Managed Code Add-in

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

David Hill, Microsoft Corporation

John R. Durant, Microsoft Corporation

November 2005

Applies to: Microsoft Visual Studio 2005 Tools for the Microsoft Office System, Microsoft Office Outlook 2003, Microsoft Visual Studio .NET 2005

Summary: Use Microsoft Visual Studio 2005 Tools for the Microsoft Office System to create a managed add-in for Microsoft Office Outlook 2003. Subscribe to blog feeds and post entries using a managed library. Use the development tools, the My.Blogs managed library, and programmable aspects of Outlook. (18 printed pages)

Download MyBlogsOutlookSetup.msi.


  • Scenario Overview

  • Exploring the Functionality

  • Exploring the Project

  • Managing the Toolbar

  • Managing Feeds, Bookmarks, and Posts

  • Configuring Add-ins

  • Working With Folders

  • Conclusion

  • Additional Resources

Scenario Overview

Blogs need no introduction. Their popularity is high, but surprisingly, the quantity and quality of blogging tools are comparatively low. Microsoft Office Outlook 2003 is an application where many people "live" during their workday, but Microsoft Office 2003 Editions do not have any built-in blogging awareness. Third-party vendors have created blogging tools, and some of these are widely embraced. You can extend these successes by creating managed code add-ins that make Outlook a vehicle for reading and writing blog entries.

Because creating managed code add-ins for Outlook has historically presented special challenges, many developers create add-ins using the Shared Add-in project template in Microsoft Visual Studio .NET 2005. But, all add-ins created and deployed using this project template load into the same application domain. This introduces security and stability issues more fully explained in Architecture of the Outlook Add-in Support in Visual Studio 2005 Tools for Office.

Now that Outlook addresses these challenges, you can focus on creating add-ins that meet real needs. Visual Studio .NET is the primary tool for creating managed code add-ins for Outlook 2003, and for other Office applications as well. Prior to the Visual Studio 2005 Tools for Office add-in tools, developers had to configure their design-time and run-time environments. For example, managed add-ins for Office applications like Outlook required a special shim between the managed environment in the add-in and the Office COM-centric environment.

Part of creating these add-ins means using the advantages of the Microsoft .NET Framework and other custom programmable libraries. One such library is My.Blogs, a GotDotNet community-driven effort initiated by the Microsoft Visual Basic team. With the APIs in the My.Blogs.DLL, you can subscribe to news feeds, manage synchronization of the feeds, and post entries to blog servers that support one of two different providers: Meta Weblog and Community Server.

Exploring the Functionality

The My.Blogs add-in described in this article creates a simple but powerful RSS aggregator within Outlook. When the add-in loads, it creates a command bar with five buttons in the primary Outlook Explorer window.

Figure 1. The custom toolbar in the add-in

These buttons allow you to access the functionality provided by the add-in. Using the add-in you can:

  • Create a blog entry and post it to your blog.

  • Create a bookmark for an Outlook item as a reminder to blog about it later.

  • Synchronize subscribed news feeds and publish written blog entries to the blog server.

  • Open the blog window.

  • Configure add-in settings.


As of this writing, the M y.Blogs programmable library supports only two blog server APIs: Meta Weblog and Community Server. Furthermore, only the Community Server API has been tested with this sample and then, only with the API set at the time that this article was written. You should consult the documentation for the blog servers you want to use to discover which providers they support. Also, it is possible that changes to the API or to the My.Blogs.DLL since the creation of this sample will cause unexpected results when running the sample. A treatment of this custom DLL and how it works is beyond the scope of this article.

In the My.Blogs add-in, you can use a bookmark feature to keep track of e-mail items that you find interesting and may want to blog about later. Additionally, the add-in lets you subscribe to RSS feeds. When the add-in synchronizes these news feeds, it downloads the latest news from the URLs you configured. During the synchronization process, the add-in also publishes pending blog posts you composed to your target blog server.

The add-in provides a blog window that shows you the status of the feeds you subscribed to, a list of bookmarked items, and a list of pending blog posts that are ready to be published to your blog.

Figure 2. The blog window in the add-in

Finally, the add-in lets you configure its operation and behavior using the MyBlogs.Outlook Options dialog box.

Figure 3. Configuring the behaviors in the add-in with the MyBlogs.Outlook Options dialog box

This dialog box allows you to choose whether to synchronize manually or automatically. It also allow you to configure the behavior of the blog window and to specify the publish URL and format for your blog server. The second tab of the dialog box lets you subscribe to feeds that interest you.

Exploring the Project

You write the project code in Visual Basic. The complete project primarily consists of forms, the ThisApplication.vb file, and classes that make it easier to work with the My.Blogs API. The project also includes utility classes to simplify routines repeatedly called at run time.


Only the most salient aspects of the code are explained in this article. However, all of it is fully commented in the download accompanying this article.

Figure 4. The main add-in project files

As is the case with many Outlook add-ins, they require a fair amount of code to keep track of the many events that occur in the host application. Unlike applications like Microsoft Office Word 2003 and Microsoft Office Excel 2003, Outlook has many places where the user can interact with the program. For example, a user can switch folders, change views, and open many types of items, such as appointments, tasks, messages, notes, and so forth. Some add-ins, like this My.Blogs add-in, need to know when a folder or Explorer changes, which folder is displayed, what type of item is opened, and what the user is viewing. In this way, the add-in can determine if it should display a toolbar, activate buttons, display a custom form, load or store data, and break things down when they are no longer needed.

Managing the Toolbar

One of the most important aspects of managing the toolbar in the My.Blogs add-in is verifying that the custom toolbar Outlook displays contains the right buttons and enables them based on which item is selected in the target Explorer. For example, if the selected item is an e-mail item, the primary Explorer that Outlook displays when starting up should display the full toolbar with all buttons enabled. If the selected item is not an e-mail item, the button for bookmarking an item is disabled while the others remain enabled.

Figure 5. Disabling a button when an item other than e-mail is selected

Another important aspect of managing the toolbar is verifying that if a user opens a secondary Explorer, the toolbar is scaled down.

Figure 6. Highlighted custom add-in toolbars in primary and secondary Explorers

In the primary Explorer, the full toolbar is displayed with one button disabled because an item other than e-mail is selected in the Explorer. In the secondary Explorer for the user's calendar, a scaled-down toolbar shows only three buttons: one for creating a new blog entry, one for creating a new bookmark (disabled because a non-mail item is selected), and one for synchronizing the subscribed feeds.

The add-in has a special class, ExplorerTracker, which indicates when to display the toolbar, how much of it to display, and which buttons to enable given the context. This class has a constructor with an argument for a pointer to the Outlook Explorer with which it is associated. It also has methods for initializing the custom toolbar and deleting the toolbar as needed. These are the Attach and Detach methods.

The main code file for the add-in ThisApplication.vb contains a startup routine, ThisApplication_Startup, which is the first method to be called when the add-in loads. In the code for this method, the add-in acquires a reference to the Explorers collection and puts this in the private variable, _explorers. Next, the add-in sets up a list of ExplorerTracker objects in _explorerTrackers. It also creates instances of the BlogFolders, BlogConfig, and BlogManager classes. (Each of these classes is explained later in this article.) Finally, the add-in creates an instance of the ExplorerTracker class for the Explorer objects that Outlook loads at startup. It then puts these instances in the _explorerTrackers list.

_explorers = Me.Explorers
_explorerTrackers = New List(Of ExplorerTracker)
_folders = New BlogFolders()
_config = New BlogConfig()

_blogManager = New BlogManager(_explorers(1))
_explorerTrackers.Add(New ExplorerTracker(_explorers(1), _
 _blogManager, False, True))

If _explorers.Count > 1 Then
    For i As Integer = 2 To _explorers.Count
        Dim explorer As Outlook.Explorer = _explorers(i)
        _explorerTrackers.Add(New ExplorerTracker(explorer, _
         _blogManager, False, False))
End If

As the user creates an Explorer object, the add-in associates a new ExplorerTracker instance with the newly created Explorer object, which is added to the existing list.

Private Sub OnNewExplorer(ByVal explorer As _
  Outlook.Explorer) _
  Handles _explorers.NewExplorer
      _explorerTrackers.Add(New ExplorerTracker _
      (explorer, _blogManager, True))
End Sub

As a new ExplorerTracker is created, the constructor accepts a pointer to the target Explorer object. It also accepts a pointer to the BlogManager instance created by the add-in at startup. Lastly, it accepts a parameter telling the instance whether it needs to be initialized when the Explorer object is activated or not. An optional parameter tells the class instance whether it is for the primary Explorer in Outlook or a secondary Explorer.

Friend Sub New(ByVal explorer As Outlook.Explorer, _
ByVal blogManager As BlogManager, _
ByVal attachOnActivate As Boolean, _
Optional ByVal primaryExplorer As Boolean = False)

    _explorer = explorer
    _blogManager = blogManager
    _attachOnActivate = attachOnActivate
    _primaryExplorer = primaryExplorer
    _attached = False

    _explorerEvents = CType(_explorer, _

    If (Not _attachOnActivate) Then
    End If
End Sub

Another important function of the ExplorerTracker is to respond when a user clicks the toolbar button for synchronization. The ExplorerTracker instance has an event handler for the Click event of the button.

Private Sub OnSynchronizeClick( _
  ByVal cmdBarbutton As Office.CommandBarButton, _
  ByRef cancelButton As Boolean) Handles _syncButton.Click

     If (_syncButton.State = _
     Microsoft.Office.Core.MsoButtonState.msoButtonUp) Then
         _syncButton.State = _
     End If
End Sub

This routine calls the StartSync method in BlogManager to start the synchronization process. As you will see, the BlogManager class is the glue that holds much of the solution together.

Managing Feeds, Bookmarks, and Posts

The BlogManager class is central to some of the main features of the add-in. One of the great benefits of the add-in is that it allows users to subscribe to news feeds. When the add-in synchronizes, it connects to subscribed feeds and downloads blog entries to specially created folders as news items.

Figure 7. Blog folders and news items after synchronization

These operations are handled by an instance of the BlogManager class. This class has methods for managing feeds, bookmarks, and blog posts written by the add-in.

Figure 8. Methods and events in the BlogManager class

The BlogManager class contains methods for handling the overall synchronization process. When the window first loads, it calls the RefreshBlogWindow method.

Friend Sub RefreshBlogWindow()
    If (_blogWindow.Visible) Then
    End If
End Sub

This method refreshes the lists of feeds, bookmarks, and posts that are exposed by the BlogWindow instance that was created in the BlogManager constructor. The BlogWindow class is the real workhorse in the solution. It does the actual refreshing of the lists.

Friend Sub RefreshFeedList()
End Sub
Friend Sub RefreshBookmarkList()
    For Each item As BookmarkItem In _
        Dim lvItem As ListViewItem
        lvItem = Me.bookmarkListView.Items.Add(item.Subject)
        lvItem.Tag = item.EntryId
        lvItem.ImageIndex = 1
End Sub
Friend Sub RefreshPostList()
    For Each item As BlogPostItem In _
        Dim lvItem As ListViewItem
        lvItem = Me.postListView.Items.Add(item.Subject)
        lvItem.Tag = item.EntryId
        lvItem.ImageIndex = 0
End Sub

These methods of the BlogWindow class access three collections of items (feeds, bookmarks, and posts) that are stored at a global level so as to be accessible from any class in the application. These collections are properties of the BlogConfig class, and are discussed later in this article.

The BlogWindow class has other members that the BlogManager class accesses for handling the creation of new bookmarks and written post entries. There are also members for handling the display of the blog window. Because this window shows up adjacent to the edge of the Outlook window, it functions as a type of task pane. However, it cannot be considered a true task pane because it does not appear within the Outlook window as does the Outlook preview pane, for example.

Figure 9. Displaying the blog window

From the blog window, the user can manage feeds, bookmarks, and blog entries by right-clicking on items. For example, the user can right-click items to open the feed's corresponding Outlook folder, and refresh the feed results; create, delete, and open a bookmarked item, and refresh the list; or open the blog entry and refresh the list. In each case, the BlogManager class calls methods in the BlogWindow class.

Earlier you learned about the ExplorerTracker class and how it is tied to the different Explorers opened when Outlook is running. Each Explorer object has a toolbar with some or all of the possible buttons displayed. One of the buttons, when clicked, kicks off the synchronization process in the BlogManager object. BlogManager has two important methods for synchronization: StartSync and CancelSync.

Friend Sub StartSync() _
Handles _blogWindow.BlogWindowStartSynchronization
    If (Not _syncManager.IsBusy) Then
        If (Globals.ThisApplication. _
        BlogConfig.AutoShowBlogWindow And _
        Not _blogWindow.Visible) Then
        End If
        RaiseEvent BlogSyncStarted(Me, _
        New EventArgs())
    End If
End Sub
Friend Sub CancelSync()

    If (_syncManager.IsBusy AndAlso _
    Not _syncManager.CancellationPending) Then
        RaiseEvent BlogSyncCancelPending( _
        Me, New EventArgs())
    End If
End Sub

Ultimately, these two methods are highly dependent on one other class, the SyncManager class. This class is responsible for the final work of synchronizing the feeds and publishing the posts to the server. This publishing process uses the My.Blogs.DLL. When the StartSync method is called, a new BackgroundWorker process is created.

Friend Sub StartSync()
      If (Not _syncWorker.IsBusy AndAlso _
      Not _syncWorker.CancellationPending) Then
          SynchronizationContext. _
          ' Start the background synchronization process.
          _syncWorker.RunWorkerAsync( _
          RaiseEvent SyncStarted()
      End If
End Sub

This background process, _syncWorker, is able to asynchronously download feeds and do other tasks. As its Worker_DoWork method is called, it publishes outgoing posts.

Private Sub PublishOutgoingPosts( _
ByVal e As System.ComponentModel.DoWorkEventArgs)
    Dim outbox As Outlook.MAPIFolder = _
  If (outbox.Items.Count > 0) Then
    Dim publishUrl As String = _
    Dim blogID As String = _
    Using logonForm As New LogonForm( _
        If (logonForm.ShowDialog() = _
        DialogResult.OK) Then
          _syncWorker.ReportProgress(0, Nothing)
          Dim itemIndex As Integer = 0
          Dim itemCount As Integer = outbox.Items.Count
          Do Until outbox.Items.Count = 0
            If (_syncWorker.CancellationPending) Then
                e.Cancel = True
                Exit Do
            End If

            Dim post As Outlook.PostItem
            post = TryCast(outbox.Items(1), Outlook.PostItem)
            If (post IsNot Nothing) Then

                My.Blogs.PublishEntry( _
                Globals.ThisApplication. _
                BlogConfig.BlogPublishFormat, _
                publishUrl, blogID, _
                logonForm.UserName, _
                logonForm.Password, _
                post.Subject, post.HTMLBody)

              Catch ex As System.Runtime. _
                ' Check for E_ABORT in case the user chose not to allow
                ' access to the HTMLBody property. In this case do not
                ' append the error message since this would result in
                ' another attempt to access the HTMLBody property.
                If (ex.ErrorCode = &H80004004) Then
                    MoveSyncErrorPost(post, _
                    "Post aborted by user.")
                    MoveSyncErrorPost(post, ex.Message)
                End If
              Catch ex As Exception
                MoveSyncErrorPost(post, ex.Message)
              End Try
            End If

            ' Report progress as percentage of total items in this feed.
            _syncWorker.ReportProgress( _
            CInt((itemIndex / itemCount) * 100), Nothing)
          ' Report final progress.
          _syncWorker.ReportProgress(100, Nothing)
        End If
    End Using
  End If
End Sub

If there are items in the Outbox folder, then the add-in attempts to publish them using configuration settings for the target blog server. (This is explained later in the article.) The add-in prompts the user for credentials to log on to the blog server for publishing posts. If the user does not stop the process, then the add-in loops through each item in the folder and tries to publish it to the blog server. If an error occurs, the item and error message are placed in a special folder so that the user can investigate the error later.

Perhaps the most important part of the routine is this method call:

My.Blogs.PublishEntry( _
            Globals.ThisApplication. _
            BlogConfig.BlogPublishFormat, _
            publishUrl, blogID, _
            logonForm.UserName, _
            logonForm.Password, _
            post.Subject, post.HTMLBody)

This example calls the My.Blogs.DLL by using the PublishEntry method. All along, the add-in reports on its progress as it loops through items in the folder, successfully removing them after each one is handled.

Just as the SyncManager class does the heavy lifting for publishing blog entries, it also does the same type of work for downloading feeds. The Worker_DoWork method contains a call to the UpdateFeedFolder method in the SyncManager class.

Private Sub UpdateFeedFolder( _
ByRef rootFolder As Outlook.MAPIFolder, ByRef feed As BlogFeed)
        ' Report initial progress.
        feed.StatusMessage = _
        String.Format(System.Globalization. _
        CultureInfo.InvariantCulture, "Synchronizing...")
        _syncWorker.ReportProgress(0, feed.FeedUrl)

        Dim myBlogsfeed As MyBlogs.Feed
        myBlogsfeed = My.Blogs.Read(feed.FeedUrl)

        If (myBlogsfeed IsNot Nothing) Then

            ' Update the title property in case it has changed.
            feed.FeedTitle = myBlogsfeed.Title

            ' Create or find the folder for this feed.
            Dim feedFolder As Outlook.MAPIFolder = _
            GetFeedFolder(rootFolder, myBlogsfeed.Title)

            ' Keep track of the date of the last post.
            Dim latestItem As Date
            latestItem = feed.LatestItemDate

            Dim itemIndex As Integer = 0
            Dim itemCount As Integer = _
            For index As Integer = myBlogsfeed. _
            Entries.Count - 1 To 0 Step -1
                Dim entry As MyBlogs.FeedEntry = _

                If (_syncWorker.CancellationPending) Then
                    Exit For
                End If

                If (entry.PublicationDate > latestItem) Then
                    latestItem = entry.PublicationDate
                    CreatePostItem(feedFolder, entry)
                    itemIndex = itemIndex + 1
                End If

                feed.StatusMessage = String.Format( _
                System.Globalization.CultureInfo. _
                InvariantCulture, "Updating Folder...")
                _syncWorker.ReportProgress( _
                CInt((itemIndex / itemCount) * 100), _
            feed.LatestItemDate = latestItem
            ' Report success.
            feed.StatusMessage = String.Format( _
            InvariantCulture, "Last Update {0}", _
            feed.Status = FeedStatus.Synchronized
        End If
    Catch ex As System.Exception
        feed.StatusMessage = ex.Message
        feed.Status = FeedStatus.SyncError
    End Try
    ' Report final progress.
    _syncWorker.ReportProgress(100, feed.FeedUrl)
End Sub

In this procedure, the add-in gets an instance of a My.Blogs.Feed object. Using this object, the add-in can acquire the collection of entries and place those in a target folder designated for that feed. (You will read about working with folders later in this article.) As before, the add-in reports its progress and signals any errors that it encounters. The BlogManager and SyncManager classes work well because they are not cluttered with routines for getting and setting configuration properties for the add-in. This is safely managed by the BlogConfig class.

Configuring Add-ins

As previously mentioned, the add-in makes use of the BlogConfig class. An instance of this class is created when the add-in is loaded. This class is important because it maintains lists shared across the entire application and holds settings for the behavior of the add-in. For example, when the user sets the synchronization timing for the add-in, the resulting value is maintained by the BlogConfig instance.

Figure 10. Configuring add-in settings

When the MyBlogs.Outlook Options dialog box opens, the code reads the existing setting from the class instance where it is stored. The property definition is as follows:

Friend Property SyncSchedule() As SyncSchedule
        Return _blogSyncSchedule
    End Get
    Set(ByVal value As SyncSchedule)
        _blogSyncSchedule = value
    End Set
End Property

The SyncSchedule class definition is a simple enumeration.

Public Enum SyncSchedule
    Manual = 0
    EveryTenMinutes = 1
    EveryHour = 2
End Enum

Other settings governing add-in behavior, such as the display of the blog window and the target blog server settings, are also stored in the BlogConfig class. Another important property is the name of the root folder where the items retrieved from news feeds are stored. This is important to other classes like the BlogFolders class.

Friend ReadOnly Property RootFolderName() As String
        Return ROOT_FOLDER
    End Get
End Property

The setting is read-only and returns a constant containing the name of the root folder, RSS, for all of the folders pertaining to new feeds.

Working With Folders

Many Outlook add-ins either interact with the built-in offering of folders or with custom folders created to fulfill purposes of the add-in. The My.Blogs add-in is more concerned with the latter than the former. Three types of folders are created, but only one can have multiple instances. The add-in creates a root folder, RSS. Below the root folder it creates three folders.

Figure 11. Folders created by the add-in

The last two folders are named Outbox and Sync Errors. When the user writes new posts and clicks the Post button, the item moves to the Outbox folder created by the add-in. When the add-in synchronizes feeds, it also attempts to push the content from posted items in the Outbox to the blog whose settings the user set at an earlier time. If for some reason the add-in cannot successfully post the content to the configured blog server, it creates a note containing the error information and places this item in the SyncErrors folder.

Additionally, the add-in creates a separate folder for each of the feeds the user has added. For example, the user has deleted the feed that appears by default after first installing the add-in, and has added a new feed.

Figure 12. Configuring a feed using the MyBlogs.Outlook Options dialog box in the add-in

Managing these folders occurs in the BlogFolders class. When the user adds a new feed and synchronization occurs, the BlogFolders class is responsible for creating a new folder for the feed, if one does not already exist. This also occurs when the add-in is first created and the root, Outbox, and Sync Errors folders are created.

Private Shared Function FindOrCreateFolder _
 (ByVal parentFolder As Outlook.MAPIFolder, _
 ByVal folderName As String) As Outlook.MAPIFolder

    Dim folder As Outlook.MAPIFolder = Nothing
    folder = FindFolder(parentFolder, folderName)
    If folder Is Nothing Then
        folder = parentFolder.Folders.Add(folderName, _
    End If
    Return folder
End Function

This example calls the FindFolder method to find out if a folder of a given name already exists.

Private Shared Function FindFolder( _
ByVal parentFolder As Outlook.MAPIFolder, _
ByVal folderName As String) As Outlook.MAPIFolder

    Dim childFolder As Outlook.MAPIFolder = Nothing
    For Each folder As _
    Outlook.MAPIFolder In parentFolder.Folders
        If folder.Name.Equals(folderName) Then
            childFolder = folder
            Exit For
        End If
    Next folder
    Return childFolder
End Function

This same method is called elsewhere in the class. For example, when the blog window is displayed, the user can see the list of configured news feeds. The user can double-click on a feed in that list to open the folder containing items downloaded from the feed. In this case, the BlogManager class makes this call:

Private Sub OnBlogWindowOpenFeedFolder( _
 ByVal sender As Object, ByVal e As BlogItemEventArgs) _
Handles _blogWindow.BlogWindowOpenFeedFolder
    Dim feed As BlogFeed = Globals. _
    Globals.ThisApplication.BlogFolders. _
End Sub

This routine calls the OpenFeedFolder method of the BlogFolders class. OpenFeedFolder attempts to locate the folder using the private FindFolder function. If it succeeds, it opens the folder using the SelectFolder method in the Outlook object model.

Friend Sub OpenFeedFolder(ByVal feedTitle As String)
    Dim rootFolder As Outlook.MAPIFolder = Me.RootFolder
    Dim feedFolder As Outlook.MAPIFolder = _
    FindFolder(rootFolder, feedTitle)
    If (feedFolder IsNot Nothing) Then
        Globals.ThisApplication.ActiveExplorer(). _
    End If
End Sub

As with the BlogConfig class, the BlogFolders class is important because it removes clutter and confusion from other classes that do more complex operations. Also, placing these operations in helper classes makes it possible to use them in other customizations or in new functionality added to the Outlook add-in later.


It is true that blogs are more than a fad. They are now an important part of the information worker's daily work. Using Visual Studio 2005 Tools for the Microsoft Office System, you can create stable and more secure add-ins for Outlook that bring the power of blogging right into one of the most popular applications ever created. Because of the add-in development and run-time environment, it is much easier to build, deploy, and maintain managed code Outlook add-ins than doing so without these new tools. Now, you can more confidently use the full power of the Microsoft .NET Framework in your Outlook customizations.

The sample accompanying this article gives you a great starting point for your own solution, and it shows some best practices and techniques that will help you with any add-in that you choose to create.

Additional Resources

For more information about developing custom solutions with Visual Studio Tools for Office, see the following resources: