WinWord.exe не будет закрываться после вызова Word.Documents.Add - Word .NET Interop - PullRequest
20 голосов
/ 25 марта 2010

Я сталкиваюсь с классическим сценарием, в котором при создании объектов Word COM в .NET (с помощью сборки Microsoft.Office.Interop.Word) процесс WinWord не завершается, даже если я правильно закрытие и отпускание объектов .

Я сузил его до использования метода Word.Documents.Add (). Я могу работать с Word другими способами без проблем (открытие документов, изменение содержимого и т. Д.), И WinWord.exe завершает работу, когда я говорю об этом. Когда я использую метод Add () (и только при добавлении шаблона ), процесс остается запущенным.

Вот простой пример, который воспроизводит проблему:

Dim word As New Word.Application()
word.Visible = False

Dim documents As Word.Documents = word.Documents
Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath), NewTemplate:=False, DocumentType:=Word.WdNewDocumentType.wdNewBlankDocument, Visible:=False)

'' dispose objects
doc.Close()
While (Marshal.ReleaseComObject(doc) <> 0)
End While
doc = Nothing

While (Marshal.ReleaseComObject(documents) <> 0)
End While
documents = Nothing

word.Quit()
While (Marshal.ReleaseComObject(word) <> 0)
End While
word = Nothing

GC.Collect()

Как видите, я правильно создаю и удаляю объекты, даже делая дополнительный шаг, чтобы зациклить Marsha.ReleaseComObject, пока он не вернет правильный код. Работа с объектами Word хороша в других отношениях, это просто противные Документы. Добавлю, что вызывает у меня горе. Есть ли еще один объект, который создается в этом процессе, на который мне нужно ссылаться и распоряжаться? Есть ли еще один шаг по утилизации, которому я должен следовать? Что-то другое? Ваша помощь очень ценится:)

Update: Я попробовал GC.Collect в конце этапа утилизации, но все равно не повезло.

Update 2: Я сузил проблему до использования пользовательских шаблонов. Когда я вызываю Documents.Add (...), я указываю пользовательский шаблон для нового документа. Если я не сделаю этого и вместо этого вызову Add () без параметров, проблема не произойдет.

Ответы [ 13 ]

0 голосов
/ 25 марта 2010

Не следует отбрасывать объект документа, созданный в Word.Documents.Add . Сохраните и вызовите Marshal.ReleaseComObject для каждого COM-объекта, который вы получаете из автоматизации, когда вы закончите, то есть , если вы нигде не кэшируете объекты .

0 голосов
/ 25 марта 2010

Хотя это C #, но, возможно, это поможет вам. Я использую этот метод для объединения нескольких документов в один. Я передаю все документы в Arraylist, и Word, кажется, закрывается должным образом, когда закончите.

 public static void documentsMerge(object fileName, ArrayList arrayList) {
        // object fileName = Path.Combine(Environment.CurrentDirectory, @"NewDocument.doc");
        File.Delete(fileName.ToString());
        try {
            wordApplication = new ApplicationClass();
            var doc = wordApplication.Documents.Add(ref missing, ref missing, ref missing, ref missing);
            try {
                doc.Activate();
                int count = 0;
                foreach (var alItem in arrayList) {
                    addDocument(alItem, doc, count == 0);
                    count++;
                }
               // addDocument(@"D:\Projects\WordTests\ConsoleApplication1\Documents\Doc1.doc", doc ) ; //, false);
               // addDocument(@"D:\Projects\WordTests\ConsoleApplication1\Documents\Doc2.doc", doc ) ; //, true);
                doc.SaveAs(ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
            } finally {
                doc.Close(ref missing, ref missing, ref missing);
            }
        } finally {
            wordApplication.Quit(ref missing, ref missing, ref missing);
        }
    }

Блок finally полезен для cleaning up любых ресурсов, выделенных в блоке try, а также для запуска любого кода, который должен выполняться, даже если есть исключение. Управление всегда передается блоку finally независимо от выхода из блока try.

Так попробуйте поместить свой код в блок try / finally и посмотрите, как он себя ведет?

Для VB.NET

Try
' Statement which can cause an exception.
Catch x As Type
' Statements for handling the exception
Finally
End Try 'Any cleanup code
0 голосов
/ 25 марта 2010

имеет ли "oDocuments" метод .Dispose () или .Close ()? вы избавляетесь от двух других, но не от этого.

...