Outlook Interop

Outlook 2007 object model incorporates the CDO 1.21 library




The only real difference between the VSTO 2005 Outlook 2003 add-in and the add-ins in VSTO 2005 SE is that the add-in host item base class wraps the Outlook Application PIA object
VSTO does not add any functionality to the Outlook object model
VSTO does not create any host items or host controls


Outlook Add-ins

These differ from Excel and Word add-ins because they must be registered in the registry
This means you must use a Setup Project to install your add-in.
When you create an Outlook add-in a setup project is automatically created for you ??
Outlook add-ins do not support Smart Tags, Task Pane Customisation or Data Caching.



Security

The security requirements of Outlook add-ins match those of Excel and Word document-level customisation.
By default VSTO solutions are very secure and require Code Access Security (CAS)
The security model in Outlook 2003 was improved with an email security update to help protect users from email viruses
This security model (often referred to as the Outlook Object Model Guard) prevents access to certain members of the Outlook object model.
It automatically trusts all installed COM Add-ins provided that you access the outlook objects through the Outlook application object (ThisApplication)
If you create a new instance then calls are restricted


Use ThisApplication instead of creating a new instance of an Application object


When Outlook is used with Exchange Server administrators can specify that all VSTO add-ins be trusted because they can specify that the AddinLoader.dll be trusted.


If macro security is set to VeryHigh or High then the add-in must be signed with a certificate
The AddinLoader.dll that shipped with VSTO was not signed, but installing VSTO 2005 SE will replace it with a signed version.



The Outlook Shutdown Issue

The Outlook shutdown problem occurs when there are unreleased references to the Outlook objects in a COM add-in (implementing IDTExtensibility2) when the application is closed
Because there are still references to Outlook objects, the OnDisconnection method never gets called and Outlook doesn't get closed properly
Even though the Outlook user interface might not be visible, Outlook is still running (task manager has outlook.exe)


VSTO helps address this issue by keeping track on the number of Inspectors and Explorers that are opened and closed
When no more windows are open in Outlook, it indicates that Outlook has closed and VSTO ensures that Outlook is shut down properly
It does this by unloading the application domain in which the add-ins were loaded and releasing the references to any COM objects
It is important to release though that you still might experience problems when Outlook closes if you are automating Outlook and you are create a running instance of Outlook without making it visible or opening any of its windows (if no Inspectors or Explorers are opened then VSTO cannot track them)


Events

The main difference between the NewMail and NewMailEx events is that with the NewMailEx you get information about each of the items based on its ID.


You should use the Shutdown event handlers rather than QuitEvent because the add-in is unloaded before this event is raised



VSTO Add-ins (Outlook specific)

Visual Studio 2005 introduced the first VSTO type add-in which was only available for Outlook 2003.
This add-in model allowed Microsoft to get some valuable feedback before modifying the add-in model slightly before releasing Visual Studio 2005 SE.
The most significant change was to remove the host item base class (that wrapped the application PIA and made the add-in version specific) and replace it with an unwrapped application PIA object as a field in the class.
It is extremely easy to migrate an old style Outlook add-in to the new Outlook VSTO model.
The original VSTO 2005 Outlook add-in projects are still available in Visual Studio versions meaning that there are 2 VSTO add-in project types for Outlook 2003.


2003 add-ins will be registered the way that Office 2003 expects and uses VSTO runtime v2 even if it is running in Office 2007.



Object Model


Outlook custom property pages


Application
Inspectors
Inspector
Outlook Item
Explorers
Explorer
Folder
Items
Folders
Namespace



ApplicationEvents_11_Events - contains all the events defined for Outlook 2007


Application.ActiveExplorer
Application.ActiveInspector
Application.ActiveWindow
Application.Session
Application.GetNamespace
Application.Explorers()
Application.Inspectors()
Application.Reminders()



Select Name dialog box - SelectNamesDialog.Display()
objNamespace.PickFolder()


Outlook Ribbon
Use the Context property of the Ribbon class to get the Outlook Inspector object for the window
The Context property returns an object that can be cast to an Outlook.Inspector object





Stores Collection

This represents all the stores in the current Outlook profile

objFolderRoot = Application.Session.DefaultStore.GetRootFolder 


Store Object

This represents a file that stores email messages and other items.
If you are using an Exchange Server, this file might be:
1) on a server in a public folder
2) on a local computer in a pst file
3) on a local computer in an offline folder file (ost)


Declaring Events

Here is an example of how to declare an event handler for the Application Startup event

Application.Startup += new Outlook.ApplicationEvents_11_StartupEventHandler(Event_ApplicationStartup) 
public void Event_ApplicationStartup()
{
}



Application.Quit

((Outlook.ApplicationEvents_11_Event)Application).Quit += new Outlook.ApplicationEvents_11_QuitEventHandler(Event_ApplicationQuit) 
public void Event_ApplicationQuit()
{
}
Addhandler 

Inspector.Close



Inspector.Activate

((Outlook.InspectorEvents_10_Event)inspector).Activate += new Outlook.InspectorEvents_10_ActivateEventHandler(Event_InspectorActivate) 
public void Event_InspectorActivate()
{
}
Addhandler 

Explorer.Activate

((Outlook.ExplorerEvents_10_Event)explorer).Activate += new Outlook.ExplorerEvents_10_ActivateEventHandler(Event_ExplorerActivate) 
public void Event_ExplorerActivate()
{
}
Addhandler 

Explorer.Close




MailItem.Send




Item.Close

((Outlook.ItemEvents_10_Event)mailitem).Close += new Outlook.ItemEvents_10_CloseEventHandler(Event_ItemClose) 
public void Event_ItemClose()
{
}
Addhandler 

// start of COM objects 
private object applicationObject = null;
private Outlook.Application m_Outlook = null;
private Outlook.NameSpace m_NameSpace = null;
private Office.COMAddIn addInInstance = null;

// Event-aware references to Explorers collection & Explorer object
private Outlook.Explorers m_Explorers = null;
private Outlook.ExplorersClass m_ExplorersClass = null;
private Outlook.Explorer m_Explorer = null;
private Outlook.ExplorerClass m_ExplorerClass = null;

// Event-aware references to Inspectors collection & Inspector object
private Outlook.Inspectors m_Inspectors = null;
private Outlook.InspectorsClass m_InspectorClass = null;
private Outlook.Inspector m_Inspector = null;
private Outlook.InspectorClass m_InspectorClass = null;
// end of COM objects

// Explorer Wrapper Collection
private System.Collections.SortedList m_ExplWrap = null;

// Inspector Wrapper Collection
private System.Collections.SortedList m_InspWrap = null;

private string m_ProgID = "";
private int m_WrapperID = 0;

private int m_OutlookVersion = 0;

//Initialization flags
private bool m_Teardown = false;
private bool m_Init = false;




applicationObject = application;
try
{
m_Outlook = (Outlook.Application)application;
m_NameSpace = m_Outlook.GetNamespace("MAPI");
//event-aware reference to Explorers collection
//use NewExplorer event to watch for UI creation
m_Explorers = m_Outlook.Explorers;
try
{
m_Teardown = false;
//Are we starting with UI?
if (m_Explorers.Count > 0)
{
m_Explorer = m_Outlook.Explorers[1];
//we have UI - initialize base class
InitHandler();
if (m_Init == true)
{
// allot space initially for 10 open Explorers at a time
m_ExplWrap = new System.Collections.SortedList(10);
OutExpl adder = new OutExpl();
m_WrapperID = adder.AddExpl(m_Explorer,
m_WrapperID, ref m_ExplWrap);
adder = null;
}

m_Inspectors = m_Outlook.Inspectors;


//After the initializations are finished for the open Explorerto put it in a sorted list and the Inspectors collec-
//tion is initialized, the event handlers are added for the NewExplorer, ExplorerClose, and NewInspector
//events.


m_Explorers.NewExplorer += new 
Outlook.ExplorersEvents_NewExplorerEventHandler(m_Explorers_NewExplorer);
m_ExplorerClass = (Outlook.ExplorerClass)m_Explorer;
m_ExplorerClass.ExplorerEvents_Event_Close += new
Outlook.ExplorerEvents_CloseEventHandler(m_Explorer_Close);
m_InspectorsClass = (Outlook.InspectorsClass)m_Inspectors
m_InspectorsClass.NewInspector += new
Outlook.InspectorsEvents_NewInspectorEventHandler(m_InspectorsClass_NewInspector);
}
else
{
//do nothing
//monitor Explorers collection (in this module)
//if NewExplorer event is raised then we have UI
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
TearDown();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
TearDown();
}
}



private void m_Explorers_NewExplorer(Microsoft.Office.Interop.Outlook.Explorer 
Explorer)
{
//assign ActiveExplorer
m_Explorer = Explorer;

if (m_Init == false)
{
//we didn't have UI before - initialize addin objects
InitHandler();
}
if (m_Init == true)
{
OutExpl adder = new OutExpl();
m_WrapperID = adder.AddExpl(Explorer, m_WrapperID, ref m_ExplWrap);
adder = null;
}
}


The code in Listing6.15 shows the event handler for the Explorer.Closeevent. When Explorer.Close
fires, the module-level m_Exploreris assigned to ActiveExplorer. If that fails, and there are no open
Inspectors, the Teardown()procedure is called to release all Outlook objects. The code in Listings 6.15
and 6.16 is only needed if you aren't using Explorerwrappers and aren't using VSTO 2005 SE. Similar
code is used in the Explorerand Inspectorwrappers to handle the Closeevents.
Listing6.15

// Monitor Explorer_Close to see when UI "disappears" 
private void m_Explorer_Close()
{
//release current reference
m_Explorer = null;
try
{
m_Explorer = m_Outlook.ActiveExplorer();
}
catch
{
if (m_Outlook.Inspectors.Count == 0)
{
//release addin objects
if (m_Teardown == false) TearDown();
}
}
}
#endregion

When a new Inspectoris opened, it's checked to make sure it's not a Note Inspector, and if not a
module level m_InspectorClassobject is instantiated as the new Inspectorfor event-handling pur-
poses as shown in Listing6.16.
Inspectorevents that are overloaded by Inspectormethods, such as Close, are handled not by
theInspectorobject but by the InspectorClassobject in C#. This also applies to other objects
where events are overloaded by methods with the same name.



An event handler for the Inspector.Closeevent is created to allow the code to handle the closing of 
the new Inspector.
m_InspectorClass.InspectorEvents_Event_Close += new
Outlook.InspectorEvents_CloseEventHandler(molInspector_Close);
Then the new Inspectoris added to the Inspectorwrapper sorted list.

#region inspector_related_events
private void m_InspectorsClass_NewInspector(Outlook.Inspector Inspector)
{
//No handling of Inspectors for Notes, they are brain dead
// set up to get the Class property of the item in the Inspector
object item = Inspector.CurrentItem;
Type _type;
_type = item.GetType();
object[] _args = new Object[] { }; // dummy argument array
Outlook.OlObjectClass _class = Outlook.OlObjectClass.olNote;
try // try to get the Class using reflection
{
_class = (Outlook.OlObjectClass)_type.InvokeMember("Class",
BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty, null, item,
_args);
}
catch (Exception ex)

{
//MessageBox.Show(ex.Message);
_class = Outlook.OlObjectClass.olNote;
}
if (_class != Outlook.OlObjectClass.olNote) {
m_Inspector = Inspector;
a try
{
m_InspectorClass = (Outlook.InspectorClass)m_Inspector;
m_InspectorClass.InspectorEvents_Event_Close += new
Outlook.InspectorEvents_CloseEventHandler(molInspector_Close);
OutInsp adder = new OutInsp();
m_WrapperID = adder.AddInsp(Inspector, m_WrapperID, _class, ref
m_ExplWrap);
adder = null;
}

catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

When the Inspectorcloses, the Closeevent handler assigns ActiveInspectorto m_Inspector, and
if that fails and there are no open Explorers, the Teardown()procedure is called to release the Outlook
objects, as shown below. The code in Listing6.17 is used only if wrapper classes aren't being used.

private void molInspector_Close() 
{
m_Inspector = null;
try
{
m_Inspector = m_Outlook.ActiveInspector();
}
catch
{
if (m_Inspector == null)
{
if (m_Outlook.Explorers.Count == 0)
{
if (m_Teardown == false)
{
TearDown();
}
}
}
}
}





private void TearDown() 
{
if (m_Teardown == false)
{
try
{
if (m_ExplWrap != null)
{
m_ExplWrap.Clear();
m_ExplWrap = null;
}
if (m_InspWrap != null)
{
m_InspWrap.Clear();
m_InspWrap = null;
}
// remove the event handlers
if (m_Explorers != null)
{
m_Explorers.NewExplorer -= new
Outlook.ExplorersEvents_NewExplorerEventHandler(
m_Explorers_NewExplorer);
}

if (m_InspectorsClass != null)
{
m_InspectorsClass.NewInspector -= new
Outlook.InspectorsEvents_NewInspectorEventHandler(
m_InspectorsClass_NewInspector);
}
//release reference to Outlook objects
if (m_Explorer != null) m_Explorer = null;
if (m_Explorers != null) m_Explorers = null;
if (m_Inspectors != null) m_Inspectors = null;
if (m_Inspector != null) m_Inspector = null;
if (m_ExplorersClass != null) m_ExplorersClass = null;
if (m_ExplorerClass != null) m_ExplorerClass = null;
if (m_InspectorsClass != null) m_InspectorsClass = null;
if (m_InspectorClass != null) m_InspectorClass = null;
if (m_NameSpace != null) m_NameSpace = null;
if (m_Outlook != null) m_Outlook = null;
if (applicationObject != null) applicationObject = null;
if (addInInstance != null) addInInstance = null;

m_Teardown = true;
m_Init = false;
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}


© 2024 Better Solutions Limited. All Rights Reserved. © 2024 Better Solutions Limited TopPrevNext