Disposing of Microsoft.Office.Interop.Word.Applica

2019-01-03 10:22发布

(Somewhat of a follow on from the post (which remains unanswered): https://stackoverflow.com/q/6197829/314661)

Using the following code

Application app = new Application();
_Document doc = app.Documents.Open("myDocPath.docx", false, false, false);
doc.PrintOut(false);
doc.Close();

I am attempting to open and print a file programmatically.

The problem is each time I run the above code a new WINWORD.exe process is started and obviously this quickly eats up all the memory.

The application class doesn't seem to contain a dispose/close or similar method.

After a bit of research I (realized) and changed the code to the following.

 Application app = new Application();
 _Document doc = app.Documents.Open(fullFilePath + ".doc", false, false, false);
 doc.PrintOut(false);
 doc.Close();
 int res = System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
 int res1 = System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

And I can see the remaining reference count is zero but the processes remain?

PS: I'm using Version 14 of the Microsoft.Office.Interop library.

7条回答
唯我独甜
2楼-- · 2019-01-03 10:40

Try this..

doc.Close(false);
app.Quit(false);
if (doc != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
if (app != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
doc = null;
app = null;
GC.Collect();
查看更多
Explosion°爆炸
3楼-- · 2019-01-03 10:40

I close the document, then the application, that works for me, then force garbage collection.

// Document
object saveOptionsObject = saveDocument ? Word.WdSaveOptions.wdSaveChanges : Word.WdSaveOptions.wdDoNotSaveChanges;
this.WordDocument.Close(ref saveOptionsObject, ref Missing.Value, ref Missing.Value);

// Application
object saveOptionsObject = Word.WdSaveOptions.wdDoNotSaveChanges;
this.WordApplication.Quit(ref saveOptionsObject, ref Missing.Value, ref Missing.Value); 

GC.Collect();
GC.WaitForPendingFinalizers();
查看更多
smile是对你的礼貌
4楼-- · 2019-01-03 10:44

The best solution.. last:

try {

    Microsoft.Office.Interop.Word.Application appWord = new Microsoft.Office.Interop.Word.Application();
    appWord.Visible = false;
    Microsoft.Office.Interop.Word.Document doc = null;
    wordDocument = appWord.Documents.Open((INP), ReadOnly: true);

    wordDocument.ExportAsFixedFormat(OUTP, Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF);

    // doc.Close(false); // Close the Word Document.
    appWord.Quit(false); // Close Word Application.
} catch (Exception ex) {
    Console.WriteLine(ex.Message + "     " + ex.InnerException);
}
查看更多
可以哭但决不认输i
5楼-- · 2019-01-03 10:47

I think the main issue, which nobody seems to have picked up on, is that you shouldn't be creating a new Application object in the first place if Word is already open. Those of us who have been coding since the days of COM and/or VB6 will remember GetActiveObject. Fortunately .Net only requires a ProgID.

The recommended way of doing this is as follows:

try
{
    wordApp = (word.Application) Marshal.GetActiveObject("Word.Application");
}
catch(COMException ex) when (ex.HResult == -2147221021)
{
    wordApp = new word.Application();
}
查看更多
放荡不羁爱自由
6楼-- · 2019-01-03 10:48

You need to calls app.Quit() to close the application. I used below code & it worked like a charm for me -

try
{
   Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
   wordApp.Visible = false;
   Microsoft.Office.Interop.Word.Document doc = null;

   //Your code here...

   doc.Close(false); // Close the Word Document.
   wordApp.Quit(false); // Close Word Application.
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message + "     " + ex.InnerException);
}
finally
{
   // Release all Interop objects.
   if (doc != null)
      System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
   if (wordApp != null)
      System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
   doc = null;
   wordApp = null;
   GC.Collect();
}
查看更多
Viruses.
7楼-- · 2019-01-03 10:49

Perhaps try setting doc = null and calling GC.Collect()

Edit, not really my own code I forget where I got it but this is what I use to dispose of Excel, and it does the job maybe you can glean something from this:

public void DisposeExcelInstance()
{
    app.DisplayAlerts = false;
    workBook.Close(null, null, null);
    app.Workbooks.Close();
    app.Quit();
    if (workSheet != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);
    if (workBook != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook);
    if (app != null)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
    workSheet = null;
    workBook = null;
    app = null;
    GC.Collect(); // force final cleanup!
}
查看更多
登录 后发表回答