C# Items.NewItem handler only handles once...

  • Thread starter Thread starter Matthew Whitworth
  • Start date Start date
M

Matthew Whitworth

I'm trying to write an Outlook Add-in using C# and interop that will
examine each incoming MailItem as it is added to the default inbox. And,
yes, I have *now* read article after article in here telling me that I
really need to use Extended MAPI in C++ or Redemption to do this
appropriately, which I will look into. But I've stumbled across something
that I think is worth trying to figure out with my C# version.

I am trying to access each MailItem via the ItemsEvents_ItemAddEvent()
delegate. (I've seen multiple posts suggesting that this is more reliable
than the Application.NewMail handler.) The first time I ran the program
in the debugger, the program saw each MailItem as it arrived and my
handler was called repeatedly. However, since then on repeated runs the
handler is called only for the first MailItem received after program
launch -- all subsequent MailItems are ignored. Not sure why this would
change.

I have rewritten the program several times from scratch, with the same
results. Here is a the smallest code sample I can generate that will
demonstrate the problem:

namespace Dumb
{
using System;
using System.Diagnostics;
using Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
using Extensibility;
using System.Runtime.InteropServices;

[GuidAttribute("..."), ProgId("Dumb.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
public Connect() { }

public void OnConnection(object application,
Extensibility.ext_ConnectMode connectMode,
object addInInst, ref System.Array custom)
{
outlook = (Outlook.Application)application;
addInInstance = addInInst;
}

public void OnDisconnection(Extensibility.ext_DisconnectMode
disconnectMode, ref System.Array custom) { }

public void OnAddInsUpdate(ref System.Array custom) { }

public void OnStartupComplete(ref System.Array custom)
{ // add the handler to default folder's ItemAddEvent...
mapi = outlook.GetNamespace("MAPI");
inbox =
mapi.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
inbox.Items.ItemAdd +=
new Outlook.ItemsEvents_ItemAddEventHandler(InboxItems_ItemAdd);
}

public void OnBeginShutdown(ref System.Array custom) { }

private void InboxItems_ItemAdd(object item)
{ // just tell me you were handled...
Debug.WriteLine("New Mail!");
}

private Outlook.Application outlook;
private Outlook.NameSpace mapi;
private Outlook.MAPIFolder inbox;
private object addInInstance;
}
}

There's nothing more fun than watching code that worked just fine thirty
minutes ago fail. Thoughts?


Matthew Whitworth
 
Matthew,

The problem is the line: inbox.Items.ItemAdd +=

The Items object is the event source for the ItemAdd event and as part of a
compound statement it's being created as temporary variable at method scope.
When the event source goes out of scope after returning from the method
call, events continue to be raised only until the .NET garbage collector
gets around to cleaning up. This is why it appears to work for a few times
initially.

Declare Items as a private variable in the main Add-In class so that it
sticks around for the duration of the session.

private Outlook.Items items;
.....
items = inbox.Items;
items.ItemAdd +=
new Outlook.ItemsEvents_ItemAddEventHandler(InboxItems_ItemAdd);


Mike


Matthew Whitworth said:
I'm trying to write an Outlook Add-in using C# and interop that will
examine each incoming MailItem as it is added to the default inbox. And,
yes, I have *now* read article after article in here telling me that I
really need to use Extended MAPI in C++ or Redemption to do this
appropriately, which I will look into. But I've stumbled across something
that I think is worth trying to figure out with my C# version.

I am trying to access each MailItem via the ItemsEvents_ItemAddEvent()
delegate. (I've seen multiple posts suggesting that this is more reliable
than the Application.NewMail handler.) The first time I ran the program
in the debugger, the program saw each MailItem as it arrived and my
handler was called repeatedly. However, since then on repeated runs the
handler is called only for the first MailItem received after program
launch -- all subsequent MailItems are ignored. Not sure why this would
change.

I have rewritten the program several times from scratch, with the same
results. Here is a the smallest code sample I can generate that will
demonstrate the problem:

namespace Dumb
{
using System;
using System.Diagnostics;
using Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
using Extensibility;
using System.Runtime.InteropServices;

[GuidAttribute("..."), ProgId("Dumb.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
public Connect() { }

public void OnConnection(object application,
Extensibility.ext_ConnectMode connectMode,
object addInInst, ref System.Array custom)
{
outlook = (Outlook.Application)application;
addInInstance = addInInst;
}

public void OnDisconnection(Extensibility.ext_DisconnectMode
disconnectMode, ref System.Array custom) { }

public void OnAddInsUpdate(ref System.Array custom) { }

public void OnStartupComplete(ref System.Array custom)
{ // add the handler to default folder's ItemAddEvent...
mapi = outlook.GetNamespace("MAPI");
inbox =
mapi.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
inbox.Items.ItemAdd +=
new Outlook.ItemsEvents_ItemAddEventHandler(InboxItems_ItemAdd);
}

public void OnBeginShutdown(ref System.Array custom) { }

private void InboxItems_ItemAdd(object item)
{ // just tell me you were handled...
Debug.WriteLine("New Mail!");
}

private Outlook.Application outlook;
private Outlook.NameSpace mapi;
private Outlook.MAPIFolder inbox;
private object addInInstance;
}
}

There's nothing more fun than watching code that worked just fine thirty
minutes ago fail. Thoughts?


Matthew Whitworth
 
Back
Top