none
Correctly releasing child COM objects RRS feed

  • Question

  • I have developed a simple Outlook plugin and am in the process of ensuring that all COM objects are properly released after I have finished using them in my code. Documentation on this seems to be a bit fragmented but thanks to various posts from the likes of Ken Slovak, Andrei Smolin and others, I think I am getting a handle on how and where this needs to be done. However I do have two questions that arise around the re-assignment of COM object members within a parent COM object.

    (Note that I appreciate that there are various arguments around the necessity of releasing COM objects. In this case I wish to understand the mechanics of releasing COM objects so that I can do it properly in those instances where I deem it necessary.)

    My two (related) questions come from the following code snippet:

    private void SetDefaultAccount(Outlook.MailItem mItem)
    {
        Outlook.Account account = FindDefaultAccount();
        mItem.SendUsingAccount = account;
        Marshal.ReleaseComObject(account);
    }
    
    private Outlook.Account FindDefaultAccount()
    {
        // Cycle through Application.Session.Accounts to find 
        // my default account name and return that account.
        //
        // Assume this works correctly and that all the COM 
        // resources are correctly built and released (eg do not
        // use a foreach nor chain up child members refs etc)
    }

    Question 1: Is the above implementation correct in not needing to assign the chained child object reference mItem.SendUsingAccount to a temporary object since it is on the LHS of the assignment? If so then how does the original Outlook.Account COM object that is initailly pointed to by mItem.SendUsingAccount get released? Maybe the implementation should be something more like:

    Outlook.Account account = mItem.SendUsingAccount; // Release existing Outlook.Account COM object Marshal.ReleaseComObject(account); // Assign new account object

    account = FindDefaultAccount(); Marshal.ReleaseComObject(account);

    Question 2: Should I release the Outlook.Account account object at all. If this is released then what is mItem.SendUsingAccount left pointing at in the parent MailItem object?

    I appreciate that I'm probably missing something fundamental in COM object handling so any guidance would be welcome.

    Wednesday, February 22, 2012 4:16 PM

Answers

  • 1. Yes, if Outlook wants to hold a reference to the Account object when you set the SendUsingAccount property (I doubt it), there is nothing you can do.

    2. Yes. Again, I doubt Outlook will hold a reference to the Account object internally. I have not seen the source code obviously, but I am 99% sure it will read the account name and id and use the values to set a couple of named properties. It will not hold a reference to teh object passed as an argument.

    You should also make sure that your FindDefaultAccount impementation releases the objects correctly.

    I would not worry too much about the Account object - it won't open an RPC channel. You do need to worry about these things when you process a large number of messages, recipients, attachments in a loop. Otherwise just let .Net do its thing unless there is a very specific reason or an error that you are trying to fix.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!

    Wednesday, February 22, 2012 4:41 PM
  • Hello,

    Until you call anything = mItem.SendUsingAccount; the beast is in the cage, no COM object is created and you don't need to release it. And mItem.SendUsingAccount = anything doesn't create a new COM object, too; it just assigns a new value to the property.

    As to releasing account in this code:

    private void SetDefaultAccount(Outlook.MailItem mItem)
    {
        Outlook.Account account = FindDefaultAccount();
        mItem.SendUsingAccount = account;
        Marshal.ReleaseComObject(account);
    }
    
    You can check the correctness of this by invoking any property from mItem.SendUsingAccount - if this produces an exception (...RCW was separated...) then you don't need to release account.

    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    Wednesday, February 22, 2012 4:54 PM

All replies

  • 1. Yes, if Outlook wants to hold a reference to the Account object when you set the SendUsingAccount property (I doubt it), there is nothing you can do.

    2. Yes. Again, I doubt Outlook will hold a reference to the Account object internally. I have not seen the source code obviously, but I am 99% sure it will read the account name and id and use the values to set a couple of named properties. It will not hold a reference to teh object passed as an argument.

    You should also make sure that your FindDefaultAccount impementation releases the objects correctly.

    I would not worry too much about the Account object - it won't open an RPC channel. You do need to worry about these things when you process a large number of messages, recipients, attachments in a loop. Otherwise just let .Net do its thing unless there is a very specific reason or an error that you are trying to fix.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!

    Wednesday, February 22, 2012 4:41 PM
  • Hello,

    Until you call anything = mItem.SendUsingAccount; the beast is in the cage, no COM object is created and you don't need to release it. And mItem.SendUsingAccount = anything doesn't create a new COM object, too; it just assigns a new value to the property.

    As to releasing account in this code:

    private void SetDefaultAccount(Outlook.MailItem mItem)
    {
        Outlook.Account account = FindDefaultAccount();
        mItem.SendUsingAccount = account;
        Marshal.ReleaseComObject(account);
    }
    
    You can check the correctness of this by invoking any property from mItem.SendUsingAccount - if this produces an exception (...RCW was separated...) then you don't need to release account.

    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    Wednesday, February 22, 2012 4:54 PM
  • Thanks for that Andrei. I had in fact already done that very test (invoking any property from mItem.SendUsingAccount) and it did not raise the RCW separated exception - it's good to have your input so I know it was a valid test to perform.

    Wednesday, February 22, 2012 8:39 PM
  • Thanks for the clear response Dmitry.
    Wednesday, February 22, 2012 8:40 PM