3

I have the below method for spellchecking in my in house app. As a new programmer this was pieced together through multiple sources and tweaked until it worked for me.

As I grow and learn I come across things that make me go, hmm. Like this SO post,How to properly clean up Excel interop objects in C#, that talks about proper Interop cleanup.

I noticed it mentions repeatedly the use of Marshal.FinalReleaseComObject() or Marshal.ReleaseComObject().

My question is this, based on the code below do I need this as well? Thanks

        public string CheckSpelling(string text)
    {
        Word.Application app = new Word.Application();
        object nullobj = Missing.Value;
        object template = Missing.Value;
        object newTemplate = Missing.Value;
        object documentType = Missing.Value;
        object visible = false;
        object optional = Missing.Value;
        object savechanges = false;
        app.ShowMe();

        Word._Document doc = app.Documents.Add(ref template, ref newTemplate, ref documentType, ref visible);

        doc.Words.First.InsertBefore(text);
        Word.ProofreadingErrors errors = doc.SpellingErrors;

        var ecount = errors.Count;
        doc.CheckSpelling(ref optional, ref optional, ref optional, ref optional, 
            ref optional, ref optional, ref optional, ref optional, ref optional, 
            ref optional, ref optional, ref optional);
        object first = 0;
        object last = doc.Characters.Count - 1;
        var results = doc.Range(ref first, ref last).Text;
        doc.Close(ref savechanges, ref nullobj, ref nullobj);
        app.Quit(ref savechanges, ref nullobj, ref nullobj);

        return results;
    }
Community
  • 1
  • 1
Refracted Paladin
  • 12,096
  • 33
  • 123
  • 233

2 Answers2

2

I would say definitely. You should always use Marshal.ReleaseComObject to clean up unmanaged COM references in .NET code.

Steve Danner
  • 21,818
  • 7
  • 41
  • 51
  • So I would be looking at adding these 3 lines? `Marshal.ReleaseComObject(doc); Marshal.ReleaseComObject(app); Marshal.ReleaseComObject(errors);` – Refracted Paladin Jan 13 '10 at 19:44
  • Yes, I would say that should take care of it. You'll want to make sure you wrap the existing code in a try...finally block and release the COM objects in the finally block to ensure they actually do get cleaned up. – Steve Danner Jan 13 '10 at 20:22
  • Thanks! Last clarification, and I will look into it myself as well, do I not need `Marshal.FinalReleaseComObject()` as well? I am unsure how that differs is al. – Refracted Paladin Jan 13 '10 at 20:34
  • 1
    According to the documentation `Marshal.FinalReleaseComObject()` is the same as invoking `Marshal.ReleaseComObject()` in a loop until it returns 0 indicating it was released successfully. Thus it's safer and better practice to use `Marshal.FinalReleaseComObject()`. – Keith Apr 09 '10 at 15:04
1

You also should explicitly create and release intermediate objects. In the case of Word._Document doc = app.Documents.Add(...);, you are implicitly creating a _Documents object that needs to be released. You should break it into two lines:

Word._Documents docs = app.Documents;
Word._Document doc = docs.Add(...);
// release docs and doc after use

It's often called the two dots rule. Anytime that there are two dots in COM interop code, you probably need to break it out, so the same rule would apply to doc.Words.First.InsertBefore(text); line.

CtrlDot
  • 3,102
  • 3
  • 25
  • 32