Why does AppointmentItem.UserProperties.Find leak under .NET?

If you have used COM under .NET then you are probably familiar with leaking memory under .NET and the need to call ReleaseComObject in order to release underlying COM objects which are referenced by .NET code.

I ran into an issue where a customer was running into a leak  with the call below:

oUserProperty = oAppointmentItem.UserProperties.Find("MyDreams", True)

Calling ReleaseComObject on oUserProperty still resulting a leak.  But why?   Well, that one call is actually several underlying calls down at the COM level and  there is a UserProperties returned which needs to be released.

This  oAppointmentItem.UserProperties.Find("MyDreams",True)  breaks down to something like this…

1.  Get the UserProperties collection.

2.  Search through the collection.

3.  Return the found property back.

So, prior the code was releasing the object in #3.  However, the object from #1 also needed to be released.

One thing about .NET is that all COM objects under .NET are still COM objects.  With COM programming such operations are different calls.  When VBA is used the memory is released, however.NET is used here and not VBA.   So, code needs to obtain a handle to the collection being used for the Find in order to release it – which means breaking out the call into separate pieces so that each item can be released by ReleaseComObject calls.

So, the following code leaks because the underlying call to get the returned collection for UserProperties is not being released.

oUserProperty = oAppointmentItem.UserProperties.Find("MyDreams", True)
ReleaseComObject(oUserProperty)

This does not leak because the oUserProps collection can be released.

oUserProps = oAppointmentItem.UserProperties
oUserProperty = oUserProps.Find("MyDreams", True)
ReleaseComObject(oUserProperty)
ReleaseComObject(oUserProps)

So, if your finding a leak be sure to break .NET wrapped COM objects where compound calls are made and release object.

Note that can tell if you have an item leak by running Outlook a second time with the "/reportleakedrenitems" command switch.  Be sure not to close the original Outlook instance when doing this.  This command will cause notepad to show identifying information for each detected item leak.

Usage:  Outlook /reportleakedrenitems

 Also see:

OOM.NET: Part 2 - Outlook Item Leaks
https://blogs.msdn.com/b/mstehle/archive/2007/12/07/oom-net-part-2-outlook-item-leaks.aspx