P
Philip Enny
Any help with this issue would be greatly appreciated. In creating an Outlook
Addin, via an IDTExtensibility2 implementation, if I access the
ActiveInspector function of the Outlook application object from a
System.Timer, Outlook will not close and will remain in memory. Consider the
following addin:
using System;
using Extensibility;
using System.Runtime.InteropServices;
using System.Timers;
using System.Diagnostics;
using Microsoft.Office.Interop.Outlook;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
namespace OutlookTestExtensibilityAddin
{
#region Read me for Add-in installation and setup information.
// When run, the Add-in wizard prepared the registry for the Add-in.
// At a later time, if the Add-in becomes unavailable for reasons such as:
// 1) You moved this project to a computer other than which is was
originally created on.
// 2) You chose 'Yes' when presented with a message asking if you wish to
remove the Add-in.
// 3) Registry corruption.
// you will need to re-register the Add-in by building the
OutlookTestExtensibilityAddinSetup project,
// right click the project in the Solution Explorer, then choose install.
#endregion
/// <summary>
/// The object for implementing an Add-in.
/// </summary>
/// <seealso class='IDTExtensibility2' />
[GuidAttribute("B2D209D5-78F3-4DCF-AFE4-92C913B35373"),
ProgId("OutlookTestExtensibilityAddin.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method. ///
/// </summary>
///
Microsoft.Office.Interop.Outlook.Application outlookApp;
System.Timers.Timer sampleTimer;
DateTime previousDateTime;
public Connect()
{
InitializeSystemTimer();
Debug.WriteLine("Connect ctor called...");
}
private void InitializeSystemTimer()
{
sampleTimer = new System.Timers.Timer();
sampleTimer.Elapsed += sampleTimer_Elapsed;
sampleTimer.Interval = 250;
}
int InOutCount = 0;
private void TimerElapsed()
{
Debug.WriteLine("In Count: " + ++InOutCount);
TimeSpan ts = DateTime.Now.Subtract(previousDateTime);
previousDateTime = DateTime.Now;
Debug.WriteLine("Timespan: " + ts.Milliseconds + " mSecs");
Inspector inspector = null;
try
{
inspector = outlookApp.ActiveInspector();
}
finally
{
inspector = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
Debug.WriteLine("Out Count: " + --InOutCount);
}
void sampleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
TimerElapsed();
}
/// <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)
{
Debug.WriteLine("OnConnection called...");
outlookApp = (Microsoft.Office.Interop.Outlook.Application)application;
ApplicationEvents_11_Event events = outlookApp;
events.Quit += new ApplicationEvents_11_QuitEventHandler(events_Quit);
}
void events_Quit()
{
sampleTimer.Stop();
}
/// <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)
{
Debug.WriteLine("OnDisconnection called...");
}
/// <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)
{
Debug.WriteLine("OnAddInsUpdate called...");
}
/// <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)
{
Debug.WriteLine("OnStartupComplete called...");
sampleTimer.Start();
previousDateTime = DateTime.Now;
}
/// <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)
{
Debug.WriteLine("OnBeginShutdown called...");
sampleTimer.Stop();
sampleTimer.Dispose();
}
}
}
Outlook 2003 will not unload if this addin is loaded. I need to have a timer
(or a seperate thread) to poll the state of an external device and take
action only if an ActiveInspector exists. Greatly appreciate any help on
this. I've tried Marshal.ReleaseComObject also to no avail.
Another suggestion or observation was that I was not releasing the
application object in OnDisconnection or OnBeginShutdown. However, neither of
these are being called as the call to ActiveInspector is causing reference to
an Inspector object. If I use a System.Windows.Form.Timer everything works
fine but because there is some time spent checking the external device, the
UI freezes.
Addin, via an IDTExtensibility2 implementation, if I access the
ActiveInspector function of the Outlook application object from a
System.Timer, Outlook will not close and will remain in memory. Consider the
following addin:
using System;
using Extensibility;
using System.Runtime.InteropServices;
using System.Timers;
using System.Diagnostics;
using Microsoft.Office.Interop.Outlook;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
namespace OutlookTestExtensibilityAddin
{
#region Read me for Add-in installation and setup information.
// When run, the Add-in wizard prepared the registry for the Add-in.
// At a later time, if the Add-in becomes unavailable for reasons such as:
// 1) You moved this project to a computer other than which is was
originally created on.
// 2) You chose 'Yes' when presented with a message asking if you wish to
remove the Add-in.
// 3) Registry corruption.
// you will need to re-register the Add-in by building the
OutlookTestExtensibilityAddinSetup project,
// right click the project in the Solution Explorer, then choose install.
#endregion
/// <summary>
/// The object for implementing an Add-in.
/// </summary>
/// <seealso class='IDTExtensibility2' />
[GuidAttribute("B2D209D5-78F3-4DCF-AFE4-92C913B35373"),
ProgId("OutlookTestExtensibilityAddin.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method. ///
/// </summary>
///
Microsoft.Office.Interop.Outlook.Application outlookApp;
System.Timers.Timer sampleTimer;
DateTime previousDateTime;
public Connect()
{
InitializeSystemTimer();
Debug.WriteLine("Connect ctor called...");
}
private void InitializeSystemTimer()
{
sampleTimer = new System.Timers.Timer();
sampleTimer.Elapsed += sampleTimer_Elapsed;
sampleTimer.Interval = 250;
}
int InOutCount = 0;
private void TimerElapsed()
{
Debug.WriteLine("In Count: " + ++InOutCount);
TimeSpan ts = DateTime.Now.Subtract(previousDateTime);
previousDateTime = DateTime.Now;
Debug.WriteLine("Timespan: " + ts.Milliseconds + " mSecs");
Inspector inspector = null;
try
{
inspector = outlookApp.ActiveInspector();
}
finally
{
inspector = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
Debug.WriteLine("Out Count: " + --InOutCount);
}
void sampleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
TimerElapsed();
}
/// <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)
{
Debug.WriteLine("OnConnection called...");
outlookApp = (Microsoft.Office.Interop.Outlook.Application)application;
ApplicationEvents_11_Event events = outlookApp;
events.Quit += new ApplicationEvents_11_QuitEventHandler(events_Quit);
}
void events_Quit()
{
sampleTimer.Stop();
}
/// <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)
{
Debug.WriteLine("OnDisconnection called...");
}
/// <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)
{
Debug.WriteLine("OnAddInsUpdate called...");
}
/// <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)
{
Debug.WriteLine("OnStartupComplete called...");
sampleTimer.Start();
previousDateTime = DateTime.Now;
}
/// <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)
{
Debug.WriteLine("OnBeginShutdown called...");
sampleTimer.Stop();
sampleTimer.Dispose();
}
}
}
Outlook 2003 will not unload if this addin is loaded. I need to have a timer
(or a seperate thread) to poll the state of an external device and take
action only if an ActiveInspector exists. Greatly appreciate any help on
this. I've tried Marshal.ReleaseComObject also to no avail.
Another suggestion or observation was that I was not releasing the
application object in OnDisconnection or OnBeginShutdown. However, neither of
these are being called as the call to ActiveInspector is causing reference to
an Inspector object. If I use a System.Windows.Form.Timer everything works
fine but because there is some time spent checking the external device, the
UI freezes.