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
Comments
- Anonymous
August 04, 2015
I've been seeing more of these types of memory leaks lately. The real problem is with properties that return an object that must be disposed/released. Years ago, there were conventions about this type of operation and in this case, the "UserProperties" property should instead be a method named "CopyUserProperties()" or "GetCopyOfUserProperties()" or something similar. This would make it clear that you are receiving a copy that you are responsible for.