Как заставить выйти из 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 не будет завершен или "отпущен"

Excel взаимодействие COM не закрывается

Неоднозначность в коде Word 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);
}
Другие вопросы по тегам