Утилизация Microsoft.Office.Interop.Word.Application - PullRequest
37 голосов
/ 21 июля 2011

(что-то вроде продолжения из поста (который остается без ответа): https://stackoverflow.com/q/6197829/314661)

Использование следующего кода

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

Я пытаюсь открыть и напечатать файл программным путем.

Проблема в том, что каждый раз, когда я запускаю приведенный выше код, запускается новый процесс WINWORD.exe, и, очевидно, он быстро израсходует всю память.

Класс приложения, кажется, не содержитметод удаления / закрытия или аналогичный метод.

После небольшого исследования я (понял) и изменил код на следующий.

 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);

И я вижу, что оставшийся счетчик ссылок равен нулюно процессы остаются?

PS: я использую версию 14 библиотеки Microsoft.Office.Interop.

Ответы [ 7 ]

50 голосов
/ 21 июля 2011

Вам не нужно звонить Quit?

app.Quit();
40 голосов
/ 21 июля 2011

Возможно, попробуйте установить doc = null и позвонить GC.Collect()

Редактировать, не совсем мой собственный код, я забыл, где я его взял, но это то, что я использую для удаления Excel, и он выполняет свою работу, может быть, вы можете что-то почерпнуть из этого:

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!
}
3 голосов
/ 25 августа 2015

Лучшее решение .. последнее:

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);
}
2 голосов
/ 12 декабря 2013

Вам необходимо позвонить app.Quit(), чтобы закрыть приложение.Я использовал приведенный ниже код, и он работал для меня как шарм -

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();
}
1 голос
/ 16 августа 2018

Я думаю, что главная проблема, которую никто, похоже, не заметил, заключается в том, что вам не следует создавать новый объект Application, если Word уже открыт.Те из нас, кто занимался кодированием со времен COM и / или VB6, будут помнить GetActiveObject.К счастью .Net требует только ProgID.

Рекомендуемый способ сделать это следующим образом:

try
{
    wordApp = (word.Application) Marshal.GetActiveObject("Word.Application");
}
catch(COMException ex) when (ex.HResult == -2147221021)
{
    wordApp = new word.Application();
}
1 голос
/ 14 марта 2018

Попробуйте это ..

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();
0 голосов
/ 21 июля 2011

Я закрываю документ, затем приложение, которое работает для меня, затем принудительно собираю мусор.

// 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();
...