zchpit
zchpit

Reputation: 3121

Microsoft.Office.Interop.Word memory leak on file create

I have class like this:

    public class WordInteropFileCreator
{
    public void CreateWordDocument(object fileName, object saveAs, string clientFullName, ClientAdressInfo clientAdressInfo)
    {
        //Set Missing Value parameter - used to represent
        // a missing value when calling methods through
        // interop.
        object missing = System.Reflection.Missing.Value;

        //Setup the Word.Application class.
        Word.Application wordApp = new Word.ApplicationClass();

        //Setup our Word.Document class we'll use.
        Word.Document aDoc = null;

        // Check to see that file exists
        if (File.Exists((string)fileName))
        {
            DateTime today = DateTime.Now;

            object readOnly = false;
            object isVisible = false;

            //Set Word to be not visible.
            wordApp.Visible = false;

            //Open the word document
            aDoc = wordApp.Documents.Open(ref fileName, ref missing,
                ref readOnly, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing,
                ref missing, ref isVisible, ref missing, ref missing,
                ref missing, ref missing);

            // Activate the document
            aDoc.Activate();

            // Find Place Holders and Replace them with Values.
            this.FindAndReplace(wordApp, "<name>", clientFullName);
            this.FindAndReplace(wordApp, "<address>", clientAdressInfo.GetStreetWithNumber());
            this.FindAndReplace(wordApp, "<city>", clientAdressInfo.GetCityWithPostalCode());
            this.FindAndReplace(wordApp, "<country>",clientAdressInfo.CountryCode != null && clientAdressInfo.CountryCode.ToUpper() == "PL" ? "  " : clientAdressInfo.CountryName);
        }
        else
        {
            throw  new Exception("File dose not exist " + fileName);
        }
        //object outputFileName = fileName.Replace(".doc", ".pdf");
        object fileFormat = Word.WdSaveFormat.wdFormatPDF;

        //Save the document as the correct file name.
        aDoc.SaveAs(ref saveAs, ref fileFormat, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing);

        object saveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
        //Close the document - you have to do this.
        aDoc.Close(ref saveChanges, ref missing, ref missing);

    }

    /// <summary>
    /// This is simply a helper method to find/replace 
    /// text.
    /// </summary>
    /// <param name="WordApp">Word Application to use</param>
    /// <param name="findText">Text to find</param>
    /// <param name="replaceWithText">Replacement text</param>
    private void FindAndReplace(Word.Application WordApp,
                                object findText,
                                object replaceWithText)
    {
        object matchCase = true;
        object matchWholeWord = true;
        object matchWildCards = false;
        object matchSoundsLike = false;
        object nmatchAllWordForms = false;
        object forward = true;
        object format = false;
        object matchKashida = false;
        object matchDiacritics = false;
        object matchAlefHamza = false;
        object matchControl = false;
        object read_only = false;
        object visible = true;
        object replace = 2;
        object wrap = 1;

        WordApp.Selection.Find.Execute(ref findText,
            ref matchCase, ref matchWholeWord,
            ref matchWildCards, ref matchSoundsLike,
            ref nmatchAllWordForms, ref forward,
            ref wrap, ref format, ref replaceWithText,
            ref replace, ref matchKashida,
            ref matchDiacritics, ref matchAlefHamza,
            ref matchControl);
    }
}

and I'm using it like this:

                string firstPart = Path.Combine(reportPathDir, "first.pdf");
                string letterPath = Path.Combine(reportPathDir, repType);
                var creator = new WordInteropFileCreator();
                creator.CreateWordDocument(letterPath, firstPart, logicResult.SpecifcationClients[0].FullName, logicResult.ClientAdressInfo);
                var fs = new FileStream(secondPart, FileMode.OpenOrCreate);
                fs.Write(bytes, 0, bytes.Length);
                fs.Close();
                fs.Dispose();

And when I lunch many console applications with this code I have memory leaks. Any advices? var creator = new WordInteropFileCreator() does not have dispose method.

Upvotes: 1

Views: 1342

Answers (2)

Similar to existing answer but completes your method. That should be quit right after document close.

Quit method for Word Application:

wordApp.Quit();
  • Tip : Quit method doesn't need any input parameters.

You should quit your Word Application after your code :

public void CreateWordDocument(object fileName, object saveAs, string clientFullName, ClientAdressInfo clientAdressInfo)

{
    //Set Missing Value parameter - used to represent
    // a missing value when calling methods through
    // interop.
    object missing = System.Reflection.Missing.Value;

    //Setup the Word.Application class.
    Word.Application wordApp = new Word.ApplicationClass();

    //Setup our Word.Document class we'll use.
    Word.Document aDoc = null;

    // Check to see that file exists
    if (File.Exists((string)fileName))
    {
        DateTime today = DateTime.Now;

        object readOnly = false;
        object isVisible = false;

        //Set Word to be not visible.
        wordApp.Visible = false;

        //Open the word document
        aDoc = wordApp.Documents.Open(ref fileName, ref missing,
            ref readOnly, ref missing, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing,
            ref missing, ref isVisible, ref missing, ref missing,
            ref missing, ref missing);

        // Activate the document
        aDoc.Activate();

        // Find Place Holders and Replace them with Values.
        this.FindAndReplace(wordApp, "<name>", clientFullName);
        this.FindAndReplace(wordApp, "<address>", clientAdressInfo.GetStreetWithNumber());
        this.FindAndReplace(wordApp, "<city>", clientAdressInfo.GetCityWithPostalCode());
        this.FindAndReplace(wordApp, "<country>",clientAdressInfo.CountryCode != null && clientAdressInfo.CountryCode.ToUpper() == "PL" ? "  " : clientAdressInfo.CountryName);
    }
    else
    {
        throw  new Exception("File dose not exist " + fileName);
    }
    //object outputFileName = fileName.Replace(".doc", ".pdf");
    object fileFormat = Word.WdSaveFormat.wdFormatPDF;

    //Save the document as the correct file name.
    aDoc.SaveAs(ref saveAs, ref fileFormat, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing);

    object saveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
    //Close the document - you have to do this.
    aDoc.Close(ref saveChanges, ref missing, ref missing);
    wordApp.Quit();
}

Upvotes: 1

stuartd
stuartd

Reputation: 73253

You are not closing Word so it will remain running in the background: call this at the end of the processing.

wordApp.Quit(ref nullObj, ref nullObj, ref nullObj);

Upvotes: 0

Related Questions