OOM.NET: Part 2 - Outlook Item Leaks
Outlook item leaks are the most common OOM with .NET issues that we see and I’ve debugged enough of them to compile this list of the four basic mistakes that contribute to item leaks. An “item leak” is most commonly seen as an item that won’t refresh or can’t be saved in the Outlook UI. A common example of this problem is that a user will complain that they receive a dialog stating that they can’t save or update an appointment in Outlook when a particular AddIn is loaded. This is because the AddIn has not released the item reference and Outlook is reusing it. In order to fix the problem properly you need to look at your code for a few of the common mistakes listed below…
Outlook Processes Reuse Cached Item References
If an item is in memory in Outlook.EXE then Outlook will reuse it when another action requests it. For example, if a COM AddIn leaks an item reference and a user is interacting with that item through the UI they might not be able to save their changes all of a sudden. This is especially true if the item were to be modified in the MAPI store after it has been leaked. An easy test would be to modify the suspected leaked item using MFCMAPI while Outlook is running then open the item in the Outlook UI and try to modify it. You will get a dialog saying that the item cannot be saved if you have leaked the item.
Do Not Chain Child Object References
One of the advantages of pure .NET programming is that you don't have to worry about memory management because the garbage collector and the dispose pattern handle all of that. What we have to remember that OOM programming in .NET is not pure .NET programming ***it is COM programming in .NET*** because of that the rules of COM apply here. Every object referenced must be released. When you chain objects you lose track of a reference that you need to release.
See the example below...
// This leaks an Attachments reference
ProcessAttachments(email.Attachments);
// This doesn’t leak
Outlook.Attachments oAttachs = email.Attachments;
ProcessAttachments(oAttachs);
Marshal.ReleaseCOMObject(oAttachs);
oAttachs = null;
Since the reference to the Attachments object is maintained it can be released properly.
Leaking a Child Item Leaks the Parent
If a child item that holds an internal reference to its parent – such as attachments or recipients - is leaked then the parent is in turn leaked. In the example above, chaining and leaking the child Attachments collection of the email will cause the email itself to leak. The parent object will never get cleaned up regardless of how many times GC.Collect or ReleaseCOMObject are called.
Be Careful with foreach Loops
The basic use of a foreach loop to iterate through items in a collection that have an internal reference to their parent – see above - will leak items. Either avoid foreach loops altogether by using for loops...
// This leaks, GC.Collect will not help
foreach (Outlook.Attachment oAttach in oAttachs)
{
Marshal.ReleaseCOMObject(oAttach);
oAttach = null;
}
// This doesn’t leak
for (int i = 1; i < oAttachs.Count; i++)
for (int i = 1; i =< oAttachs.Count; i++)
{
Outlook.Attachment oAttach = oAttachs[i];
// Do nothing with attachment
Marshal.ReleaseCOMObject(oAttach);
oAttach = null;
}
…or follow the notes in this discussion to articulate the handling and cleanup of the underlying objects in the enumerator created by the foreach loop to ensure that things get cleaned up properly…
IEnumerator attachsEnum = oAttaches.GetEnumerator();
while (attachsEnum.MoveNext())
{
Attachment at = (Attachment)attachsEnum.Current;
Marshal.ReleaseCOMObject(at);
}
ICustomAdapter adapter = (ICustomAdapter)attachsEnum;
Marshal.ReleaseComObject(adapter.GetUnderlyingObject());
Marshal.ReleaseComObject(oAttaches);
*** Edited on 7/31/2009 to fix attachment loop, thanks Tobias!
Comments
Anonymous
December 15, 2007
Exchange Admin 101: Exchange 2003 and Exchange 2007 admin privileges Troubleshooting Exchange GlobalAnonymous
February 18, 2008
The Outlook Developer Reference on MSDN has great information on .NET and COM interop which I would considerAnonymous
May 22, 2008
Welcome to Outlook Programming series # 9 In this series, we will learn "How to systematically releaseAnonymous
June 12, 2008
Plan For What You Can Control One of the common scenarios in OOM programming in managed that requiredAnonymous
October 30, 2008
The latest hotfix package for Outlook was released this week which resolves many of the .NET item leakAnonymous
March 18, 2009
I had a customer who required information and advice on creating an addin for their environment. Their