Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Outlook Customization for Integrating with Enterprise Applications

 

Microsoft Corporation

January 2006

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

Summary: Improve the availability of CRM data for information workers by creating a sample Outlook add-in and associated set of utility classes using Visual Studio Tools for Office that displays enterprise CRM data naturally within the Outlook user interface. (30 printed pages)

Click here to download The CRM Integration for Outlook sample.

Contents

Executive Summary
Introduction
Architecture
VSTO Outlook Template
The Managed Utility Classes
Adding Custom Folders
Adding Custom Toolbars and Menus
Adding Custom Inspector Windows
Hosting Managed Controls in Outlook Folder Home Pages
Hosting the Outlook View Control in a Managed Add-in
Conclusion
Companion Resources
Sample Code Disclaimer

Executive Summary

Many organizations have made multi-billion dollar investments in customer relationship management (CRM) systems and line of business (LOB) applications over the last decade. Although many of these applications have delivered significant business benefits, some organizations have found that these bespoke systems have not delivered the expected returns on investment. One of the argued reasons for this is that specialized enterprise systems, databases, and applications do not integrate well with information worker workflows.

This is the third in a series of papers that presents an architectural design guide and associated sample code to enable integration of enterprise CRM and other LOB applications with Microsoft Outlook. The guidance in this paper originated from Microsoft's Project Elixir, an internal Microsoft IT initiative to integrate critical customer data within Outlook. The design uses Microsoft Visual Studio 2005 Tools for Office (VSTO), Microsoft SQL Server 2005 Express Edition (SQL Server Express), and Web services.

The sample solution uses a set of utility classes to handle the integration of elements of the Outlook user interface (UI) with a managed code add-in. This paper discusses the design of the utility classes and how they simplify and facilitate the creation of an Outlook add-in. For more information about the overall solution architecture, see Extending Enterprise Applications with Microsoft Outlook: Architectural Design Guide. For instructions on how to download the sample code, see the Microsoft CRM Integration Sample for Outlook Source Setup download page. For more information about the other papers in the series, see the Companion Resources section at the end of this paper.

Introduction

Information workers spend the majority of their time using desktop-based Office applications to manipulate and share information with their colleagues. For example, information workers are generally extremely familiar with Outlook, which they use for internal and external communications with both colleagues and customers alike. So when designing a solution to provide access to the corporate CRM system, it is a natural choice to develop an add-in for Outlook that can implement new menus, toolbars, and data forms, while still maintaining a smooth, integrated experience for users.

Creating add-ins for Outlook has historically been a challenging and sometimes complex exercise. However, with the release of VSTO 2005, developers now have a Visual Studio template they can use to accelerate the creation of Outlook add-ins using managed code. In addition to the project template, VSTO provides an improved runtime, a robust add-in loader, and better support for development, debugging, and deployment.

Specific benefits provided by an Outlook add-in solution created with a VSTO are:

  • .NET Framework programming benefits. These include the use of strongly-typed modern programming languages, automatic memory management, rich-class library support, and structured exception handling.
  • Run-time isolation. At runtime, the VSTO add-in is loaded into its own application domain by a specialized AddInLoader. This provides added security and isolation benefits. (NOTE: The Hosting Managed Controls in Outlook Folder Home Pages integration technique described later in this paper does not provide this application domain isolation.)
  • Security. An administrator can configure code access security policy to grant the add-in the FullTrust permission set required because it uses interop to access the unmanaged Outlook application.
  • Deployment. The add-in template creates a setup project that deploys the add-in and the AddInLoader component and creates the necessary registry entries.

With the release of VSTO 2005, the creation of Outlook add-ins to front-end enterprise systems becomes an increasingly realistic development option. This paper describes a sample add-in solution that provides access to back-office data held in a fictitious CRM system through the Outlook user interface. The sample add-in provides custom forms and custom processing within Outlook using the extensibility provided by the native Outlook object model. To facilitate this, the sample introduces a set of utility classes designed to simplify common Outlook development tasks and help handle the integration of custom forms with Outlook. The managed utility classes were developed with reuse in mind and may be useful in other Outlook add-in solutions.

For more information about the advantages of Outlook add-in development support in VSTO, see Architecture of the Outlook Add-in Support in Visual Studio 2005 Tools for Office.

Architecture

The key components of the high-level architecture for this sample add-in solution are shown in Figure 1. These include the Microsoft Office and Outlook primary interop assemblies (PIAs) through which the add-in code interacts with the Outlook object model, a set of managed utility classes, and the add-in application code. The managed utility classes are designed as helper classes to simplify some of the common Outlook development tasks required by the sample CRM add-in.

Click here for larger image

Figure 1. Overview of sample CRM add-in solution (Click on the image for a larger picture)

This paper discusses the design of the VSTO sample add-in, customizations to Outlook enabled by the Outlook object model, and the associated utility classes. It shows with sample code how the utility classes can be used in the specific scenario described in this series of whitepapers to enable integration of CRM data with Outlook.

VSTO Outlook Template

The VSTO Outlook add-in template adds references to several assemblies and generates code so that the Outlook object model becomes accessible to the managed code inside the Outlook add-in project. When you create a new add-in project by using the VSTO Outlook add-in template, the template creates the following:

  • An Outlook add-in project
  • A class called ThisApplication.
  • References to Outlook objects and interop assemblies.
  • A Visual Studio deployment project.

The template generates code behind the ThisApplication class to provide reliable startup and shutdown events for the add-in. The references to the Outlook objects and interoperability components enable the managed code in the add-in to reference the Outlook object model and provide interoperation between the managed code and the unmanaged COM Outlook object model at runtime.

Note   The default deployment project does not include the code for setting up a security policy to allow the add-in to run. The sample CRM add-in project includes a custom installer class (in the file Installer.cs) that has the System.ComponentModel.RunInstaller attribute set to indicate that the Visual Studio custom action installer or the installer tool (Installutil.exe) should invoke the class when the solution is installed.

References Set by the VSTO Outlook Template

The VSTO Outlook add-in template adds references to the new add-in project for several components that make the Outlook object model available. Table 1 lists the components and namespaces that are referenced for this purpose.

Table 1. Components and Namespaces Added for the Outlook Object Model

ComponentNamespaceDescription
Office CoreMicrosoft.Office.CorePrimary interop assembly. Objects common to the Office applications.
VSTO OutlookMicrosoft.Office.Tools.OutlookContains the Application class. The generated ThisApplication class derives from this Application class.
Outlook interopMicrosoft.Office.InterOp.OutlookPrimary interop assembly for the COM Outlook object model.
Visual Studio RuntimeMicrosoft.VisualStudio.ToolsProvides run-time isolation and security.

The primary access point for the code that you write in an Outlook add-in will be through the ThisApplication class generated by the VSTO template, and this is an implementation of the VSTO Outlook component's Application class.

In addition, the template generates a reference to the Office Core component. This provides access to the classes that are general to all Office applications. For example, toolbars and menus are found in the Office Core assembly.

The Outlook Object Model

The Outlook object model available to your custom add-in application code would be familiar to a Microsoft Visual Basic for Applications (VBA) developer who is used to writing macro-style code for Outlook. Figure 2 shows the important objects within the Outlook object model.

Click here for larger image

Figure 2. Selected objects within the Outlook object model (Click on the image for a larger picture)

The organization of the Outlook object model is divided between the data and the UI. The branch that includes the Session object describes the data, and the branch that includes the Explorer and Inspector objects describes the UI.

In the Outlook UI, folders are shown in the outline list on the left and the main Explorer window displays the contents of a selected folder, whereas an Inspector pops-up to show the detail of a single item. For example, Figure 3 shows Outlook with a Contacts folder selected and the main Explorer window showing a table of contact data. By double-clicking the "Howard Gonzalez" contact item, the user has popped-up his details in the default contact Inspector.

Click here for larger image

Figure 3. The main UI regions in Outlook (Click on the image for a larger picture)

In code you can access the current Explorer or Inspector objects by using the ActiveExplorer and ActiveInspector methods of the Application object. Toolbars and menus are attached to the Explorer and Inspector objects, as shown here.

private void ThisApplication_Startup(object sender, System.EventArgs e)
{
  Outlook.Explorer explorer = this.ActiveExplorer();
  Outlook.Inspectors inspector = this.ActiveInspector();
}

The preceding code shows that you can access the Outlook Application object by using the this keyword. This is possible because the ThisApplication class derives from the Application class in the VSTO Outlook assembly. (The fully-qualified name for this class is Microsoft.Office.Tools.Outlook.Application.)

In code, you can navigate to the folder being displayed by an explorer, and to the item being shown by an inspector. Figure 4 shows their relationships in part of the Outlook object model:

Aa479345.otlkcustinentapp04(en-us,MSDN.10).gif

Figure 4. The relationship between UI and data objects

Calling Office Code by Using Microsoft C#

The COM objects in the Office Core and Outlook object models expect parameters to be passed by reference, and objects in the Office Core enable optional parameters. The COM interop layer helps by converting by-value parameters into references. Visual Basic .NET supports optional parameters, but C# does not. Therefore inside the utility classes you will find that all of the parameters for a method are provided and the Type.Missing is used when not providing a parameter value. For example, this sample call provides two missing parameters.

menuBar.Controls.Add(
    Office.MsoControlType.msoControlPopup,
    Type.Missing,
    Type.Missing,
    helpMenuIndex,
    true);

For more information about calling Office code by using C#, see the paper, Programming Office Applications with Microsoft Visual C#.

The Managed Utility Classes

The goal of these classes is to simplify common Outlook development tasks and enhance the ease and speed with which a managed code Outlook add-in can be built and maintained. The classes were designed to complement and extend the baseline Outlook extensibility provided by native Outlook object model. Specifically these classes:

  • Provide additional support for toolbar and menu management.
  • Provide additional support for window and custom item management.
  • Provide a generic Outlook item type to enable polymorphic access to the baseline functionality provided by all Outlook item types.
  • Enables the synchronization of application data with a local SQL Express data store. (This topic is not covered in this paper. For more information see Synchronizing a Local Data Store with Microsoft Outlook).

Figure 5 shows the main managed utility classes created as part of the sample add-in.

Click here for larger image

Figure 5 Main managed utility classes (Click on the image for a larger picture)

The managed utility classes are:

  • CustomItemManager. This manages launching a form as a custom inspector when an Outlook item is opened in place of the default Outlook inspector. It also manages the Write event handler for standard inspectors that store data in the database, for example the Contact inspector.
  • ItemAdapter. This provides a generic adapter class for the different Outlook item types like Task, Contact, and Email. It exposes a set of properties and methods that are common to all Outlook item types, and enables the general processing of an Outlook item.
  • Folder. This has static methods to handle the selection and creation of Outlook folders.
  • FolderHomePage. This has static methods that register a Windows Forms control to be used as a custom folder home page.
  • CommandBarManager. This holds a mapping to enable the registration of toolbars and menus with inspector and explorer windows, and ensures toolbars and menus are automatically attached to all explorer and inspector windows.
  • CommandBar. This is a base class for the ToolBar and Menu classes.
  • ToolBar. This represents a toolbar that can be attached to explorer and inspector windows. A toolbar has a collection of ToolBarControl objects.
  • ToolBarControl. This is a base class for the controls that can appear on a toolbar. The implementations are ToolBarButton, ToolBarComboBox, and ToolBarTextBox.
  • Menu. This represents a menu that can be attached to explorer and inspector windows. A menu has a collection of MenuItem objects.
  • OutLookViewControl. This provides a wrapper for the ActiveX Outlook view control so it can be instantiated for use in a managed code project.

The utility classes are used in the sample add-in code to create a customized Outlook user interface that provides access to data from a fictitious CRM back-end system. The elements of the sample add-in's user interface are:

  • Custom folders. These act as a container for the CRM data.
  • Custom toolbars and menus. These provide access to CRM actions.
  • Custom inspector windows. These override the default Outlook inspectors to allow additional CRM data to be displayed and manipulated.
  • Custom folder home pages. These provide overview and summary information for the custom CRM folders.

The following sections describe in detail how the utility classes are used to create each of these user interface elements within the sample solution.

Adding Custom Folders

The sample add-in creates a new root CRM Today folder to act as the container for the CRM application's customization in Outlook. Figure 6 shows that within the CRM Today folder, new folders are added for each CRM account, and these contain the customized CRM Activities and CRM Opportunities items, as well as standard Contact items that are associated with the account.

Aa479345.otlkcustinentapp06(en-us,MSDN.10).gif

Figure 6. Custom CRM account folders under the CRM Today root folder

At startup, the add-in needs to either create the new folders or confirm that they are already present. This is accomplished using the static methods of the utility class Folder. For example, the following code is used in the sample to add the new CRM Today folder.

using Outlook = Microsoft.Office.Interop.Outlook;
using Utility = Microsoft.Sample.Outlook.Utility;
...
Outlook.MAPIFolder root = Utility.Folder.GetRootFolder(this.Session);
Outlook.MAPIFolder crmFolder = Utility.Folder.CreateFolder(
                                   root, Properties.Resources.CRMFolderName);

Note that the preceding code gets the name for the new folder from a resource string so it can be localized. You can use similar code to add new folders for the CRM accounts, but in that case the folder names will come from the CRM data.

Adding Custom Toolbars and Menus

Besides custom folders, the sample add-in also requires custom menu items and toolbar buttons to launch its custom processes and forms. This section shows how you can use the utility classes to add custom toolbars and menu items to Outlook.

The CommandBarManager class tracks the creation of new explorer and inspector windows and ensures that the correct command bars are added. Although there are several types of menus and toolbars, you implement them in a similar way. The types of menus and toolbars are:

  • Toolbar and buttons (or other controls).
  • New menus that are added to existing Outlook menus.
  • Pop-up menus.

The sample add-in creates a command bar with several buttons that allow the user to convert an e-mail item into a CRM Activity or CRM Opportunity. To facilitate this, the add-in has an object of the class CommandBarManager with private scope in the ThisApplication class. This CommandBarManager object allows menus or toolbars to be registered. It then ensures that registered toolbars and menus are added to all new Outlook explorer and inspector windows, and that the events from them are properly handled.

To create a new toolbar or menu bar:

  1. Create the new menu or toolbar object.
  2. Add controls like menu buttons to the toolbar or menu bar.
  3. Add event handlers to the controls.
  4. Register the new menu or toolbar with the CommandBarManager object.

Figure 7 shows the new custom toolbar created for the sample add-in and the new CRM Integration Sample menu placed after the standard Outlook Help menu.

Aa479345.otlkcustinentapp07(en-us,MSDN.10).gif

Figure 7. Custom menu bar inserted after the Help menu

The following code from the sample adds a new toolbar and two buttons with their associated event handlers. It also adds an event that fires just before the toolbar is displayed in an Outlook explorer or inspector window.

using Utility = Microsoft.Sample.Outlook.Utility;
...
private void CreateConvertToolbar()
{
  Utility.Toolbar crmToolbar = new Utility.Toolbar("Contoso CRM Convert");
  Utility.ToolbarButton btnCreateActivity = new Utility.ToolbarButton(
                                          "Convert to CRM Activity");
  Utility.ToolbarButton btnCreateOpportunity = new Utility.ToolbarButton(
                                          "Convert to CRM Opportunity");
  btnCreateActivity.Click += new  
             EventHandler<Utility.CommandBarEventArgs>(btnCreateActivity_Click);
  btnCreateOpportunity.Click += new 
             EventHandler<Utility.CommandBarEventArgs>(btnCreateOpportunity_Click);
  crmToolbar.Controls.Add(btnCreateActivity);
  crmToolbar.Controls.Add(btnCreateOpportunity);
  crmToolbar.BeforeShow += new 
        EventHandler<Microsoft.Sample.Outlook.Utility.BeforeShowCommandBarEventArgs>( 
                                            crmToolbar_BeforeShow);
  _commandbarManager.RegisterCommandBar(crmToolbar);
}

Notice that the preceding code uses a private CommandBarManager object called _commandbarManager. Also, for clarity in this sample, the text on the toolbar buttons has been hard-coded; in a production application, you should add these strings to the resources so that they can be localized into different languages.

Adding Custom Inspector Windows

The sample add-in implements custom inspector windows so CRM Activity and CRM Opportunity data, pulled from the database, can be displayed within the Outlook UI. The custom windows are created as managed Windows Forms classes and registered with Outlook as custom inspectors using the utility class CustomItemManager. This ensures that the custom inspector is used wherever the item is selected for inspection in Outlook. For example, Figure 8 shows the custom Opportunity inspector window that has popped-up as a result of the user double-clicking on a specific opportunity item.

Click here for larger image

Figure 8. Custom Opportunity Inspector window (Click on the image for a larger picture)

The CustomItemManager class tracks the creation of new inspector windows, substituting custom windows where appropriate. The sample add-in code has an object of class CustomItemManager with private scope in the ThisApplication class called _itemManager. The Windows Form that is used to provide the custom opportunity inspector is registered with the _itemManager when the Opportunities folder is created. For example:

using Outlook = Microsoft.Office.Interop.Outlook;
using Utility = Microsoft.Sample.Outlook.Utility;
...
Outlook.MAPIFolder opportunityFolder = Utility.Folder.CreateFolder(
            accountFolder,
            Properties.Resources.OpportunitiesFolderName,
            Outlook.OlDefaultFolders.olFolderInbox);
_itemManager.RegisterCustomForm(opportunityFolder, 
                                            typeof(ItemForms.OpportunityForm));

This means that the default inspector for the item type contained by the folder will be replaced by a Windows Form using the class OpportunityForm. Inside the CustomItemManager class, form creation is handled using reflection to find the form's constructor and check that it can be passed a reference to the item.

void CreateCustomForm(ItemAdapter adapter, Type formType)
{
  System.Reflection.ConstructorInfo ci = 
             formType.GetConstructor( new Type[] { typeof(ItemAdapter) });
  if (ci == null)
  {
    throw new ApplicationException(
       "Form types must have a constructor that takes an ItemAdapter parameter");
  }
  System.Windows.Forms.Form form = (System.Windows.Forms.Form)
                                            ci.Invoke( new object[] { adapter });
  form.Show();
}

Creating Windows Forms as Custom Inspectors

As described in the preceding section, for a Windows Form to be suitable for registration with the CustomItemManager object it must have a constructor that takes an ItemAdapter object as its parameter. This allows the CustomItemManager to pass the custom form a reference to the item being inspected when the form is instantiated for the purpose of inspecting an existing item.

The following shows the sample code for the OpportunityForm class. Note that two overloads of the constructor are provided: the first has no parameter and allows the form to be created for the purpose of adding a new opportunity item; the second overload takes an ItemAdapter reference to allow editing of an existing opportunity item.

using Utility = Microsoft.Sample.Outlook.Utility;
...
namespace Microsoft.Sample.ContosoCRM.ItemForms
{
  internal sealed partial class OpportunityForm : Form
  {
    
    Utility.ItemAdapter _opportunity;

    public OpportunityForm()
    {
      InitializeComponent();
    }
    public OpportunityForm(Utility.ItemAdapter item)
    {
      InitializeComponent();
      if (item.Class != Outlook.OlObjectClass.olPost)
      {
        throw new ApplicationException(
            "ActivityForm can only be initialized with outlook post items");
      }
      _opportunity = item;
    }
    ...
  }
}

The ItemAdapter utility class has several methods that can return the object as one of the Outlook item types. This allows the code in a custom Windows Form to access the Outlook item properties. For example, the custom opportunity form displays data using the Outlook AppointmentItem class.

using Outlook = Microsoft.Office.Interop.Outlook;
...
Outlook.AppointmentItem appt = item.GetAsAppointment();
this.textBoxComments.Text = appt.Body;
this.textBoxName.Text = appt.Subject;

The custom form can then provide processing as required by the custom add-in application before finally saving changes back into the item using the ItemAdapter utility class's Save method.

Custom Write Handlers

The CustomItemManager also manages the Write event handler for standard inspectors that store data in the database. For example, the sample CRM add-in uses the default Outlook contact inspector to display contacts associated with a CRM account. A custom write event can be registered with the CustomItemManager object when the contact folder is created, as shown here.

itemManager.RegisterWriteHandler( 
                      contactFolder, new CancelEventHandler(OnContactWrite));

When the user saves the contact data, the CustomItemManager fires the custom write event. In the sample CRM add-in, this allows the additional data with which a contact is associated to be retrieved for storage in the local database. The OnContactWrite event uses the standard sender and event arguments format, where the sender object uses an ItemAdapter to represent the Outlook contact item being saved. For example, this allows you to retrieve the identifier of the account associated with the contact item by using code similar to the following.

using Outlook = Microsoft.Office.Interop.Outlook;
using Utility = Microsoft.Sample.Outlook.Utility;
...
void OnContactWrite(object sender, CancelEventArgs e)
{
  Utility.ItemAdapter item = (Utility.ItemAdapter)sender;
  //Get the associated account ID form the parent folder's OutlookID
  Outlook.MAPIFolder folder = (Outlook.MAPIFolder)item.Parent;
  Outlook.MAPIFolder accountFolder = (Outlook.MAPIFolder)folder.Parent;
  Guid AccountID = (Guid)accountsAdapter.GetLocalID(accountFolder.EntryID);
  ...
}

Hosting Managed Controls in Outlook Folder Home Pages

One of the challenges that you may face when designing the UI for an Outlook add-in is how to make custom forms appear inside the Outlook application's main window and then interact with the other elements of Outlook. It is relatively straightforward to create a non-modal custom Windows Form in an Outlook add-in, but the form displays outside of Outlook's main window, obscuring the core Outlook UI and preventing the tight level of integration that may be desired.

The utility class FolderHomePage uses a technique that customizes an Outlook folder so that it displays an HTML file in its home page window. It can then use this HTML file to host a managed control. The FolderHomePage class adds a small script to the HTML file, so the managed control can reference and interact with the Outlook application.

Figure 9 shows the sample CRM add-in folder CRM Today selected in the Folder List. The folder home page is displaying an HTML file, and the home page is hosting a managed control to provide a custom UI. The view of the HTML file is called the folder's Web View.

Click here for larger image

Figure 9. Managed control in the CRM Today folder Web View (Click on the image for a larger picture)

Note   The approach described in this section might present problems when multiple add-ins are loaded into one instance of Outlook because it requires that components of the solution load into the default application domain. Another add-in that also loads components into the default application domain could conflict with your add-in and cause Outlook instability. For this reason it is not recommended that you use this approach for desktops that have multiple managed add-ins installed in Outlook.

Architecture

Figure 10 shows the main components at work when a folder Web View is used to host a managed control. The folder Web View is capable of displaying a Web page from an HTML file, and a Web page is able to display a Microsoft ActiveX control by using an <object> tag. So, by registering a managed control as a COM class and then referencing the same control in an <object> tag, you can make the managed control display in the Web View.

Click here for larger image

Figure 10. Architecture of hosting a managed control in a folder's Web View (Click on the image for a larger picture)

The utility class FolderHomePage writes a local HTML file containing the <object> tag referencing the managed control, and then returns its path so it can be set as the folder's WebViewURL property. For example, to create the CRM Today folder and register the control class CRMTodayView in its Web View, the sample add-in uses the following code.

using Outlook = Microsoft.Office.Interop.Outlook;
using Utility = Microsoft.Sample.Outlook.Utility;
...
Outlook.MAPIFolder root = Utility.Folder.GetRootFolder(this.Session);
Outlook.MAPIFolder crmFolder = Utility.Folder.CreateFolder(
                                   root, 
                                   Properties.Resources.CRMFolderName);
crmFolder.WebViewURL = Utility.FolderHomePage.RegisterType( 
                                 typeof(FolderHomePages.CRMTodayView));
crmFolder.WebViewOn = true; 

To host a managed control in Outlook, the add-in must create the HTML file in code and save it in a folder on the local computer that is accessible to Outlook. Inside the FolderHomePage class, therefore, the code for the RegisterType method uses a combination of the environment's local application data folder path and a custom folder name WebViewsDirectory from the add-in's resources.

string webViewDirectory =  
     Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 
                   Properties.Resources.WebViewsDirectory ); 

COM Registration

The managed control class needs to be registered in the local computer's registry as a COM class. It also has to be marked as safe for scripting in the registry. This can be achieved by Visual Studio while the add-in is being built in debug configuration, but must be performed by the installer when the add-in is being deployed.

The FolderHomePage class makes a reference to System.Runtime.InteropServices, to allow it to provide methods for the managed control to perform COM registration and unregistration when it is being debugged.

To make Visual Studio run the COM registration as part of the build, you must ensure that the Register for COM Interop option is checked in the project build properties. Visual Studio then registers the project assembly at the end of the build process. The sample project includes a custom Installer class that is marked with the System.ComponentModel.RunInstaller attribute. The installer class contains the code to perform the required COM registration when the add-in is deployed.

Communication Between the Managed Control and Outlook

A managed control of this sort is likely to need access to the objects in Outlook. But, as shown in Figure 11, it is hosted inside a Web page inside the Web View of a folder in Outlook.

Aa479345.otlkcustinentapp11(en-us,MSDN.10).gif

Figure 11. Managed control inside the Web View of an Outlook explorer

The challenge is to get a reference to the Outlook application on the outside into the managed control on the inside.

JScript Initialize Script

The FolderHomePage class addresses this problem by writing a JScript function into the folder home page HTML. The function is assigned to the document.onload event so it runs when the HTML document is loaded. The script is programmed to get a reference to the Outlook application that is hosting the control, and then to pass the reference into an Initialize method provided by the managed control. The following example shows a script function that will do this.

<script>
  function OnBodyLoad()
  {
    var objApp = document.window.external.OutlookApplication;
    HostedUserControlTest.Initialize(objApp);
  }
</script>

The FolderHomePage class determines whether the managed control has an Initialize method by using reflection. It uses code to write the HTML file like the following sample.

Type[] paramTypes = new Type[1];
paramTypes[0] = typeof(Outlook.Application);
System.Reflection.MethodInfo initInfo = viewType.GetMethod("Initialize", paramTypes);
if (initInfo == null)
{
  //There is no Initialize method with the given signature
}
else
{
  //Correct Initialize method was detected
  ...

Managed Control Initialize Method

To interact with Outlook, the managed control keeps a private reference to the Outlook application object passed into its Initialize method, as shown here.

private Outlook.Application _app;
public void Initialize(Outlook.Application obj)
{
    _app = (Outlook.Application)obj;
}

Then, the managed control can access any of the objects in the Outlook object model; for example, it can get a count of the items in the Inbox, as shown here.

Outlook.MAPIFolder mapiInbox = _app.Session.GetDefaultFolder(
        Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
int itemCount = mapiInbox.Items.Count;

Hosting the Outlook View Control in a Managed Add-In

The explorer window in the Outlook UI often displays a list view of items in an Outlook folder. This control, known as the Outlook view control, is made available by the component AxInterop.OLXLib as an ActiveX control called AxViewCtl.

Note   As with the preceding technique, the approach described in this section might present problems when multiple add-ins are loaded into one instance of Outlook because it requires that components of the solution load into the default application domain. Another add-in that also loads components into the default application domain could conflict with your add-in and cause Outlook instability. For this reason it is not recommended that you use this approach for desktops that have multiple managed add-ins installed in Outlook.

Reusing the existing Outlook view control enables you to maintain a standard UI in a custom Outlook add-in while reducing the cost of implementation. You can display the Outlook view control inside a custom form or managed control in an add-in. For example, Figure 12 shows the Outlook view control displaying a detailed list of tasks.

Click here for larger image

Figure 12. Outlook view control inside a custom managed control (Click on the image for a larger picture)

Wrapping the Outlook View Control in a Managed Control

The Outlook view control itself is an ActiveX control. It can be used from managed code through the interop class AxViewCtl directly, but it must be initialized correctly before it can be used. Therefore to facilitate its use in custom add-in projects, the sample add-in code includes the OutlookViewControl class.

The OutlookViewControl class initializes an instance of underlying ActiveX control and hides the complexity of most of its members.

using OVC = AxMicrosoft.Office.Interop.OutlookViewCtl;
public partial class OutlookControl : UserControl
{
  //  
  private OVC.AxViewCtl viewControl;
        
  public OutlookControl()
  {
    InitializeComponent();

    System.ComponentModel.ComponentResourceManager resources 
                          = new System.ComponentModel.ComponentResourceManager(
                                           typeof(OutlookControl));
    this.viewControl = new AxMicrosoft.Office.Interop.OutlookViewCtl.AxViewCtl();

    //supports the ISupportInitialize interface, so start initalize
    System.ComponentModel.ISupportInitialize iSupportInitialize = this.viewControl;
    iSupportInitialize.BeginInit();
    //initial setup of properties from AxViewCtl : AxHost
    this.viewControl.Dock = System.Windows.Forms.DockStyle.Fill;
    this.viewControl.Enabled = true;
    this.viewControl.Location = new System.Drawing.Point(0, 0);
    this.viewControl.Name = "axViewCtl1";
    this.viewControl.OcxState 
                        = ((System.Windows.Forms.AxHost.State)(resources.GetObject(
                                          "axViewCtl1.OcxState")));
    this.viewControl.Size = new System.Drawing.Size(371, 364);
    this.viewControl.TabIndex = 0;
    this.viewControl.Visible = false;
    this.Controls.Add(this.viewControl);
    //end initialize
    iSupportInitialize.EndInit();
  }
  //Expose the Outlook.Application object
  public Outlook.Application OutlookApplication
  {
    get { return (Outlook.Application)viewControl.OutlookApplication; }
  }
  //Expose the contained control
  public OVC.AxViewCtl NativeControl
  {
    get { return viewControl; }
  }
  //Expose the Folder property (string path)
  public string Folder
  {
    get { return viewControl.Folder; }
    set { viewControl.Folder = value; }
  }
  //Expose the View property
  public string View
  {
    get { return viewControl.View; }
    set { viewControl.View = value; }
  }
  //expose the ViewXML property
  public string ViewXML
  {
    get { return viewControl.ViewXML; }
    set { viewControl.ViewXML = value; }
  }
}

Displaying the Wrapped Outlook View Control

You can use the Folder property of an Outlook view control to change the folder being displayed. The Folder property requires a string that gives the path to a folder. For example, the Notes folder, immediately under the Personal Folders or Mailbox root folder, can be displayed by using the following path.

\\Personal Folders\Notes

For example, this code displays an Outlook view control for the Notes folder inside a Panel1 panel control.

OutlookControl view = new OutlookControl();
view.Name = "ovcNotes";
view.Dock = DockStyle.Fill;
view.Folder = @"\\Personal Folders\Notes";
panel1.Controls.Add(view);

Interacting with the Wrapped Outlook View Control

The Outlook view control has its own internal reference to the Outlook application, and this is exposed by the managed control wrapper as an Outlook.Application object. Therefore, a custom form that is hosting a wrapped Outlook view control can access the Outlook application, folders, and the items that it is displaying.

Conclusion

This paper provides a high-level overview of Outlook add-in development using VSTO and discusses a set of sample utility classes that has been created to facilitate common development tasks when writing a managed code add-in for Outlook. The paper demonstrates how these utility classes can be used to create a sample CRM add-in using Visual Studio Tools for Office that displays enterprise CRM data naturally within the Outlook user interface, improving the availability of CRM data for information workers.

Companion Resources

Microsoft has developed a sample Outlook add-in solution that demonstrates how the Outlook UI can be extended and customized to create a front-end for a CRM system. For more information about the "CRM Integration Add-in Sample for Microsoft Outlook" see http://download.microsoft.com/download/9/9/C/99CD8598-2A46-48A8-9A5B-7A30D46C0856/CRM Integration Sample for Outlook Source Setup.msi.

For more information about the overall integration scenario and the technical architecture used in the sample, see the Extending Enterprise Applications with Microsoft Outlook: Architectural Design Guide whitepaper.

For a more detailed discussion on how to integrate Outlook with a local data store and how to synchronize between Outlook and the local store, see the Synchronizing a Local Data Store with Microsoft Outlook whitepaper.

For more information about the internal Microsoft IT project (code-named Project Elixir) to create an Outlook front-end to Microsoft's internal CRM systems, see https://members.microsoft.com/customerevidence/search/EvidenceDetails.aspx?EvidenceID=13848&LanguageID=1.

Sample Code Disclaimer

This paper describes a sample application that is provide "as is" and without warranty. The technical approach used in this sample implementation and described in the associated whitepapers is one approach to achieve integration between Outlook and an enterprise back-end system. These techniques presented may not be appropriate for all scenarios and within all enterprise environments. Please make sure you consult the associated whitepapers which discuss the selected techniques in detail and present appropriate caveats and technical trade-offs where appropriate.

Show:
© 2015 Microsoft