4

What is the importance of using Marshal.ReleaseComObject when interacting with MailItems in Outlook?

I refer to the walkthrough on creating a C# VSTO Outlook AddIn at https://learn.microsoft.com/en-us/visualstudio/vsto/walkthrough-creating-your-first-vsto-add-in-for-outlook?view=vs-2019

Where they have an example of modifying the exiting selected mail item's subject and body.

void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
    Outlook.MailItem mailItem = Inspector.CurrentItem as Outlook.MailItem;
    if (mailItem != null)
    {
        if (mailItem.EntryID == null)
        {
            mailItem.Subject = "This text was added by using code";
            mailItem.Body = "This text was added by using code";
        }

    }
}

The example ends without any mention of releasing the mail item object using Marshal.ReleaseComObject.

But in the .Net API Reference at https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netframework-4.8, they mentioned:

You should use this method to free the underlying COM object that holds references to resources in a timely manner or when objects must be freed in a specific order.

So apparently there are some consequence if we fail to use Marshal.ReleaseComObject on the MailItem we are referencing?

Is there a specific use case where not using Marshal.ReleaseComObject will lead to problem?

Thanks

Kinjo
  • 66
  • 7

1 Answers1

5

If you don't call Marshal.ReleaseComObject, the object will be released as some later undermined point by the Garbage Collector. Normally, it is not a problem - you usually need to be careful and not leave the release to chance when processing a large number of items. In this particular case, you will be fine without Marshal.ReleaseComObject unless you want to make sure that the item is released in case it is updated externally and you don't want the Outlook Object Model to end up with a stale object.

Note that Marshal.ReleaseComObject on the mailItem variable will not be enough - you need to be careful about implicit variables, e.g. when you use a multiple dot notation. Some .Net operators also end up with implicit variables, and as is one of them (as well as is):

void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
    object item = Inspector.CurrentItem;
    Outlook.MailItem mailItem = item as Outlook.MailItem;
    if (mailItem != null)
    {
        if (mailItem.EntryID == null)
        {
            mailItem.Subject = "This text was added by using code";
            mailItem.Body = "This text was added by using code";
        }
        Marshal.ReleaseComObject(mailItem);
    }
    Marshal.ReleaseComObject(item);
}
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
  • 1
    _"you need to be careful...multiple dot notation..."_ - incorrect. _["...There is `no need` to store these object references yourself and `explicitly call` Marshal.ReleaseComObject(), the `CLR does it for you`. And it never gets it wrong, it `doesn't use` or need a "two dot rule" ..."](https://stackoverflow.com/questions/25134024/clean-up-excel-interop-objects-with-idisposable/25135685#25135685)_ - (Hans Passant) - –  Nov 21 '19 at 07:51
  • 2
    Sigh... Yes, GC will release these objects. Eventually... You do not control when. And (in case of online Exchange ) as soon as you go over 250 open RPC channels, you will get an exception. Before GC has a chance to do anything for you. You need to use Marshal.ReleaseComObject if you need to avoid that. – Dmitry Streblechenko Nov 21 '19 at 16:23
  • 1
    I see so there may be a possibility of an exception when using the mail item object in online Exchange if GC is too slow. But the usage of Marshal.ReleaseComObject may itself throw an exception if not used properly (which i probably don't know how to). In that case my best hope is to don't Release the object, but do more extensive performance testing on the AddIn to ensure stability. Thank you so much for the information – Kinjo Nov 22 '19 at 09:25