Как заставить выйти из Word, используя C# Interop
Как я могу гарантировать завершение процесса MS Word (используя библиотеку C# Interop)?
Мой текущий подход:
// close word document ("doc")
((_Document)doc).Close(SaveChanges: WdSaveOptions.wdDoNotSaveChanges);
if (doc != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
doc = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
// close word application ("word")
((_Application)word).Quit(false);
if (word != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(word);
word = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
// and here is how it fails
Process[] pname = Process.GetProcessesByName("WINWORD");
Assert.IsTrue(pname.Length == 0);
Источники:
C# MSOffice Interop Word не убивает winword.exe
Утилизация Microsoft.Office.Interop.Word.Application
Объект Microsoft.Interop не будет завершен или "отпущен"
1 ответ
Нет необходимости использовать ReleaseComObject, если вы используете методы GC для перелистывания кучи. Также имейте в виду, вам нужно вызвать методы GC дважды:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
В любом случае, я всегда рекомендую использовать https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx для освобождения объекта Office (Word), когда вы закончили его использовать. Затем установите переменную Nothing в Visual Basic (null в C#), чтобы освободить ссылку на объект. Вы можете прочитать больше об этом в статье " Систематическое высвобождение объектов". Он относится к Outlook, но те же правила могут применяться к любому приложению Office (включая Word).
В любом случае это работает для меня
Word.Application app = null;
Word.Document doc = null;
Word.Tables tables = null;
Word.ContentControls mainControls = null;
try
{
app = new Word.Application();
app.ScreenUpdating = false;
app.Visible = false;
app.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
doc = app.Documents.Open(fileName);
tables = doc.Tables;
//.. my code
if (tables.Count < 1)
val = mainControls[2].Range.Text ?? "";
//end of my code
}
catch (Exception exc) { G.log(exc); }
finally
{
//CLEAN UP
GC.Collect();
GC.WaitForPendingFinalizers();
if (mainControls != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(mainControls);
if (tables != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(tables);
if (doc != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
app.Quit();
if (app != null)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
}