Outlook 2003 VSTO framework conflicts with other apps using MAPI

S

Sanjay

Hello guys..
I have an issue with one of the apps that connects to Outlook to
retrieve calendar information. It is a windows app that displays
calendar and recent mail items. Here is the sample code

using Microsoft.Office.Interop.Outlook;
public class OutlookSource
{
private Application outlookApp;
private NameSpace outlookNS;
public void OutlookSource
{
outlookApp = new Application();
outlookNS = outlookApp.GetNamespace("MAPI");
//do some work here
}
}


What above code does is that it launches outlook in the background.
When users actually launch outlook, the ThisApplication_Startup event
does not get fired. None of the plugins get activated.

Is there a workaround for this?

Sanjay
 
D

Dmitry Streblechenko

Startup event gets fired when when the first app launches Outlook. When user
double clicks on the Outlook icon on the desktop, the already running
instance of Outlook simply displays a new Explorer.
I suspect the reason why your code does not work is because you always
assume on startup that there is at least one explorer visible where you can
add your buttons (which is not the case obviously)and you do not trap the
Application.Explorers.NewExplorer event.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
S

Sanjay

Dmitry,
Thanks for your quick response...

It seems the application_startup event is not fired when the first
app is launched. This app establishes a mapi session and reads email
from the default profile. Then when user launches Outlook, the
Application_startup event in the VSTO plugin is fired. Then when the
user closes outlook, Application_Shutdown event is fired. Then when
the user restarts it, the application_startup event is ignored.

I am using VS2005 + VSTO + C# + Outlook 2003 SP2 (11.8030.8107).

Is there a way around this issue?


Sanjay
 
K

Ken Slovak - [MVP - Outlook]

VSTO uses the StartupComplete event to fire its startup event. If other code
is holding Outlook open you won't get a new StartupComplete event and
therefore the VSTO addin won't start up again.

There are workarounds that can be used from VB.NET or C# shared addins but
none that I know of for VSTO addins.
 
S

Sanjay

Ken,
Thanks for your response..

I am assuming you are talking about using the ID2Extensibility
interface.. Can you please send me the workaround for that? I may have
to change the code to use the shard addin's instead of vsto..

Sanjay
 
K

Ken Slovak - [MVP - Outlook]

I use something like this, the code is from a C# addin template for Outlook
2007, but you can just ignore the Office 2007 specific stuff. It's a partial
copy of the code in my Connect.cs class:

namespace CSAddinTemplate
{
using System;
using Extensibility;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Windows.Forms;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Vbe.Interop.Forms;
using stdole;
using System.Drawing;
using System.Text;
using System.Diagnostics;

/// <summary>
/// The object for implementing an Add-in.
/// </summary>
/// <see also class='IDTExtensibility2' />
[GuidAttribute("B0B9C466-B680-49B6-B7E2-3EC9C9F46334"),
ProgId("CSAddinTemplate.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2,
Office.IRibbonExtensibility, Office.ICustomTaskPaneConsumer,
Outlook.FormRegionStartup
{
#region Module_level_declarations
public static string m_ProgID = "";

// start of COM objects
private object applicationObject = null;

public Outlook.Application m_Outlook = null;
private Outlook.NameSpace m_NameSpace = null;

private Office.COMAddIn addInInstance = null;

// Event-aware references to Explorers collection & ActiveExplorer
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 & ActiveInspector
private Outlook.Inspectors m_InspectorClasss = null;
private Outlook.InspectorsClass m_InspectorClasssClass = 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 int m_WrapperID = 0;

private int m_OutlookVersion = 0;

//Initialization flags
private bool m_Teardown = false;

private bool m_Init = false;

//Ribbon UI object
private Office.IRibbonUI m_Ribbon;

//CTP objects
private Office.ICTPFactory m_CTP;
private Office.CustomTaskPane CTP;
private const string CTP_PROGID = "CSAddinTemplate.EmailTaskPane";
private const string CTP_EXPL_PROGID =
"CSAddinTemplate.CustomTaskPane";
private const string CTP_TITLE = "CS Config";
private const string CTP_EXPL_TITLE = "CS WEB";

// Form Region declarations
// use the value in the <name> tag in the Region XML
private const string TIME_TRAVEL_FORM_REGION = "TimeTravel";
private Outlook.FormRegion m_FormRegion;
private TimeTravelFormRegionWrapper m_RegionWrap;

#endregion

/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method.
/// </summary>
public Connect()
{
}
#region Startup_Shutdown
/// <summary>
/// Implements the OnConnection method of the IDTExtensibility2
interface.
/// Receives notification that the Add-in is being loaded.
/// </summary>
/// <param term='application'>
/// Root object of the host application.
/// </param>
/// <param term='connectMode'>
/// Describes how the Add-in is being loaded.
/// </param>
/// <param term='addInInst'>
/// Object representing this Add-in.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application,
Extensibility.ext_ConnectMode connectMode, object addInInst, ref
System.Array custom)
{
applicationObject = application;

System.Windows.Forms.Application.EnableVisualStyles();

try
{
addInInstance = (Office.COMAddIn)addInInst;
}
catch
{
addInInstance = null;
}

if (addInInstance != null)
{
//set module level reference to COMAddIn object
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
{
//put ProgID in a module level variable
m_ProgID = addInInstance.ProgId;

//addInInstance.Object = Me
addInInstance.GetType().InvokeMember("Object",BindingFlags.Public
| BindingFlags.SetProperty, null, addInInst, new object[] { this });

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 15 open
Explorers at a time
m_ExplWrap = new
System.Collections.SortedList(15);

OutExpl adder = new OutExpl();

m_WrapperID = adder.AddExpl(m_Explorer,
m_WrapperID, ref m_ExplWrap);

adder = null;

// allot space initially for 15 open
Inspectors at a time
m_InspWrap = new
System.Collections.SortedList(15);
}

m_InspectorClasss = m_Outlook.Inspectors;

m_Outlook.OptionsPagesAdd += new
Microsoft.Office.Interop.Outlook.ApplicationEvents_11_OptionsPagesAddEventHandler(m_objOutlook_OptionsPagesAdd);
m_NameSpace.OptionsPagesAdd += new
Microsoft.Office.Interop.Outlook.NameSpaceEvents_OptionsPagesAddEventHandler(m_NameSpace_OptionsPagesAdd);

m_Explorers.NewExplorer += new
Microsoft.Office.Interop.Outlook.ExplorersEvents_NewExplorerEventHandler(m_Explorers_NewExplorer);

m_ExplorerClass =
(Outlook.ExplorerClass)m_Explorer;
m_ExplorerClass.ExplorerEvents_Event_Close +=
new
Microsoft.Office.Interop.Outlook.ExplorerEvents_CloseEventHandler(m_Explorer_Close);

m_InspectorClasss.NewInspector += new
Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(m_InspectorClasss_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();
}
}
else TearDown();
}


/// <summary>
/// Implements the OnDisconnection method of the
IDTExtensibility2 interface.
/// Receives notification that the Add-in is being unloaded.
/// </summary>
/// <param term='disconnectMode'>
/// Describes how the Add-in is being unloaded.
/// </param>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnDisconnection(Extensibility.ext_DisconnectMode
disconnectMode, ref System.Array custom)
{
if (m_Teardown == false) TearDown();
}

/// <summary>
/// Implements the OnAddInsUpdate method of the
IDTExtensibility2 interface.
/// Receives notification that the collection of Add-ins has
changed.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnAddInsUpdate(ref System.Array custom)
{
}

/// <summary>
/// Implements the OnStartupComplete method of the
IDTExtensibility2 interface.
/// Receives notification that the host application has
completed loading.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnStartupComplete(ref System.Array custom)
{
// uncomment for an Explorer task pane
//if (m_CTP != null)
//{
// try
// {
// CTP = m_CTP.CreateCTP(CTP_EXPL_PROGID, CTP_EXPL_TITLE,
m_Explorer);
// CTP.DockPositionRestrict =
Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
// CTP.DockPosition =
Office.MsoCTPDockPosition.msoCTPDockPositionRight;
// CTP.Visible = true;
// }
// catch (Exception ex)
// {
// MessageBox.Show(ex.Message);
// }
//}

}

/// <summary>
/// Implements the OnBeginShutdown method of the
IDTExtensibility2 interface.
/// Receives notification that the host application is being
unloaded.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnBeginShutdown(ref System.Array custom)
{
}

#endregion

#region utility_procedures
public void InitHandler()
{
string sVerLeft2 = "";
string sVersion = "";

//********************************************************

sVersion = m_Outlook.Version;
sVerLeft2 = sVersion.Substring(0, 2);
switch( sVerLeft2)
{
case "10":
m_OutlookVersion = 10;
break;
case "11":
m_OutlookVersion = 11;
break;
case "12":
m_OutlookVersion = 12;
break;
default:
if ((sVerLeft2.Substring(0 , 1)) == "9")
{
m_OutlookVersion = 9;
}
else
{
m_OutlookVersion = 0;
}
break;
}

//set initialization flag
m_Init = true;
}

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
Microsoft.Office.Interop.Outlook.ExplorersEvents_NewExplorerEventHandler(m_Explorers_NewExplorer);
}

if (m_InspectorClasss != null)
{
m_InspectorClasss.NewInspector -= new
Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(m_InspectorClasss_NewInspector);
}

//release Ribbon reference
m_Ribbon = null;

//release CTP references
m_CTP = null;
CTP = null;

//release form region reference
m_FormRegion = null;

//release reference to Outlook objects
if (m_Explorer != null) m_Explorer = null;
if (m_Explorers != null) m_Explorers = null;
if (m_InspectorClasss != null) m_InspectorClasss = null;
if (m_Inspector != null) m_Inspector = null;

if (m_ExplorersClass != null) m_ExplorersClass = null;
if (m_ExplorerClass != null) m_ExplorerClass = null;

if (m_InspectorClasssClass != null) m_InspectorClasssClass =
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);
}
}
}
#endregion

#region explorer_related_events
// NewExplorer event will be raised if there is UI
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 add-in objects
InitHandler();
}

if (m_Init == true)
{
OutExpl adder = new OutExpl();

m_WrapperID = adder.AddExpl(Explorer, m_WrapperID, ref
m_ExplWrap);

adder = null;
}
}

// 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 add-in objects
if (m_Teardown == false) TearDown();
}
}
}
#endregion

#region inspector_related_events
private void
m_InspectorClasss_NewInspector(Microsoft.Office.Interop.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;

try
{
m_InspectorClass = (Outlook.InspectorClass)m_Inspector;
m_InspectorClass.InspectorEvents_Event_Close += new
Microsoft.Office.Interop.Outlook.InspectorEvents_CloseEventHandler(molInspector_Close);

OutInsp adder = new OutInsp();

switch (_class)
{
case Outlook.OlObjectClass.olMail:
CTP = m_CTP.CreateCTP(CTP_PROGID, CTP_TITLE,
Inspector);
CTP.DockPositionRestrict =
Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
CTP.DockPosition =
Office.MsoCTPDockPosition.msoCTPDockPositionRight;
CTP.Visible = false;
break;
case Outlook.OlObjectClass.olAppointment:
m_RegionWrap = new TimeTravelFormRegionWrapper();
break;
default:
{
break;
}
}

// m_RegionWrap and m_Ribbon are dummies, filled in when
Ribbon_OnLoad and BeforeFormRegionShow fire
m_WrapperID = adder.AddInsp(Inspector, m_WrapperID, _class,
ref m_InspWrap, CTP, m_RegionWrap, m_Ribbon);

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

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();
}
}
}
}
}
#endregion
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top