Утилизация Microsoft.Office.Interop.Word.Application
(Отчасти продолжение этого поста (который остается без ответа): https://stackru.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, и, очевидно, это быстро израсходует всю память.
Класс приложения, похоже, не содержит метода dispose/close или аналогичного метода.
После небольшого исследования я (понял) и изменил код на следующий.
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 ответов
Возможно, попробуйте настройку 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!
}
Я думаю, что главная проблема, которую, похоже, никто не заметил, заключается в том, что вам не следует создавать новый объект 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();
}
Лучшее решение.. последнее:
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);
}
Вам нужно звонить 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();
}
Согласен с другими плакатами, GC.Collect()
а также Marshal.ReleaseComObject()
не нужен. Если процесс все еще существует после запускаapp.Quit(false)
, это может быть связано с тем, что вы запускаете приложение в невидимом состоянии, и есть приглашение, не позволяющее закрыть приложение, например диалоговое окно восстановления документа. В этом случае вам нужно добавить это при создании вашего приложения.
app.DisplayAlerts = false;
Я закрываю документ, затем приложение, которое работает для меня, затем принудительно собираю мусор.
// 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();
Попробуй это..
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();