9

In a Microsoft Office AddIn we are passed COM objects in events. To take a specific case, when Word opens a document we are called and passed a Document object. So when do we need to call Marshal.ReleaseComObject()?

  1. If we access the Document object do we need to call release on it? Or can we assume Word has already accessed it and will clean it up?
  2. If we access Document.Name that gives us a string. As a string is not a COM object we do not need to clean that up - correct?
  3. But if we access any member that returns a class that is wrapping a COM object (which is any class returned by a member method/function), we do need to call release on that - correct?

And what happens if we miss a release? Any COM object we hold onto for an indeterminate amount of time we wrap in a class of ours with IDisposable implemented. We call Dispose() when we're done. But some of the code handling this is complex and I'm guessing we have an occasional case where we're not calling Dispose.

Are we better off having a finalizer which then adds overhead for every single instance of these objects (a lot!)? Or are we better off with a small number of Word COM objects that are never released?

thanks - dave

David Thielen
  • 28,723
  • 34
  • 119
  • 193
  • 2
    There are already hundreds of questions about this, easily found by the method name. Same theme over and over again, an RCW is a managed object so observes garbage collection lifetime rules. You force a collection with GC.Collect – Hans Passant May 06 '12 at 19:08
  • 2
    I read through 12 items here on S/O on this. The above were the question I was left with after reading all of them. MS Office COM objects are a bit more complicated because you're not sure exactly what Office is doing. – David Thielen May 06 '12 at 19:10
  • 1
    There's only one kind of COM, Office doesn't use a special version of it. The more intricate the object model, the less likely that you'll punch the monkey with ReleaseComObject. Which is why you leave it up to the garbage collector, it never misses a monkey. – Hans Passant May 06 '12 at 19:12
  • Actually there are a bunch of cases where you must call ReleaseComObject() on Office objects or they remain even after your application exits. The rules are the same for all COM objects but they way they are used in Office leads to issues you rarely see elsewhere. – David Thielen May 06 '12 at 19:45
  • 3
    Black magic has no place in software engineering. There are lots more way to miss the monkey with the syntax extensions permitted in C# version 4. The Range.Cell[x, y].Value syntax is an excellent one to hide 3 monkeys that are completely un-punchable because you don't assign the interface reference anywhere. That why you leave it up to the garbage collector. – Hans Passant May 06 '12 at 19:59
  • It's not black magic, it's side effects. If you create a Workbook inside a Word AddIn and don't release every object you access, then after you close the Workbook Excel will still have a process running. If you access Document.Variables on the initial Document1 blank document and don't release it, then when the user opens another document, Document1 will remain open instead of being replaced. – David Thielen May 07 '12 at 11:57
  • @Hans Passant - here are two S/O posts that discuss why you need to release all Office COM objects. I hope this helps answer your comments. http://stackoverflow.com/questions/2926205/does-every-excel-interop-object-need-to-be-released-using-marshal-releasecomob & http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c-sharp – David Thielen May 07 '12 at 14:18
  • 2
    Yes, it is a very popular illusion. That doesn't otherwise make it the correct illusion. Only Sahuagin got it right. This keeps coming up over and over again because everybody keeps doing it wrong, which is very hard to avoid. For the exact same reason that writing a C program that doesn't leak memory is hard to do. Clearly I cannot convince you and that's not really important. Make this a real question by posting a snippet that exhibits a problem. – Hans Passant May 07 '12 at 14:30
  • I believe this is the [answer by Sahuagin](http://stackoverflow.com/a/7263538/1497596) to which Hans Passant refers. – DavidRR Jan 20 '17 at 19:08

1 Answers1

3

In short, every reference you make to a COM object must be released. If you don't, the process will stay in memory.

That excludes value types (strings, etc.) and child COM objects you have not explicitly referenced.

One exception may be COM objects passed to you as event parameters. I don't think you need to release them but I'm not certain. However a quick test should confirm that. (Try your add-in with and without releasing the COM object. See if the add-in begins to behave funny or if any related processes are left running after the app is closed.)

To address your specific questions:

  1. If we access the Document object do we need to call release on it? Or can we assume Word has already accessed it and will clean it up? -- You must release it.

  2. If we access Document.Name that gives us a string. As a string is not a COM object we do not need to clean that up - correct? -- You don't need to clean up value types.

  3. But if we access any member that returns a class that is wrapping a COM object (which is any class returned by a member method/function), we do need to call release on that - correct? -- You don't need to release it if you haven't explicitly referenced it. (There are some exceptions. For example in this question of mine I discovered that a particular COM method was instantiating a COM object and never releasing it. Since I have no control over the method implementation my only choice was to avoid using the method.)

  4. And what happens if we miss a release? -- The process (winword.exe, excel.exe, etc.) will remain in memory. Over time all of these unterminated processes will eat up all of the available memory on the machine.

  5. Are we better off having a finalizer which then adds overhead for every single instance of these objects (a lot!)? Or are we better off with a small number of Word COM objects that are never released? -- You're better off with the finalizer. Always release your COM objects! I've found that the steps outlined here are the most effective. (These steps use FinalReleaseComObject which is preferred over ReleaseComObject.) I also advise against killing the Office process as an alternative to not releasing COM. Over time this will cause issues with the Office interop (which I've never fully understood).

Community
  • 1
  • 1
Keith
  • 20,636
  • 11
  • 84
  • 125
  • First off thank you! Second, on question 1, does the Document object become marshalled when I access it and that is why I need to release it? It feels wrong to release an object that is passed in to me. THat doesn't mean it IS wrong, but it feels that way. – David Thielen May 07 '12 at 16:10
  • Sorry, I missed the fact that the Document object is being passed to you via an event parameter. I updated my question to address that. What are you using to create your add-in? You're not using VSTO? – Keith May 07 '12 at 16:49
  • We use the old IExtensibility API for our Add-In. Back when we started VSTO was really limited (don't know about now). On the try releasing and see if it gets squirly - that tends to lead to problems down the road. – David Thielen May 07 '12 at 22:26
  • After some more research I'm almost positive that you don't need to release the COM objects passed to you as event parameters. That's how it works with VSTO projects. – Keith May 09 '12 at 14:38