WinWord.exe не выйдет после вызова Word. Документы. Добавьте - Word.NET Interop

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

Я сузил его к использованию Word. Документы. Добавьте () метод. Я могу работать с Word другими способами без проблемы (вводные документы, изменяя содержание, и т.д.) и выходы WinWord.exe, когда я говорю его. Это - после того как я использую Добавление () метод (и только при добавлении шаблона), который процесс оставляют, работая.

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

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 () без параметров, то проблемы не происходит.

20
задан Berkay Turancı 7 December 2012 в 07:48
поделиться

9 ответов

Я понял, что виновато использование Documents.Add () при использовании настраиваемого шаблона . Я не могу объяснить, почему из-за этого WinWord.exe зависает. Однако есть и другие способы создания документов из шаблонов, которые не приводят к той же проблеме.

Я заменил:

Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath))

на:

Dim doc As Word.Document = documents.Add()  
doc.AttachedTemplate = templatePath  
doc.UpdateStyles()

Использование AttachedTemplate для указания шаблона работает у меня и не оставляет WinWord.exe зависшим.

(Однако возникла одна новая проблема ... Изображение в нижнем колонтитуле шаблона не копируется в документ при использовании AttachedTemplate / UpdateStyles. Я рассматриваю это как отдельную проблему. Но поскольку этот метод решает мой исходный проблема, я доволен. Спасибо всем, кто дал ответы!)

2
ответ дан 30 November 2019 в 00:51
поделиться

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

0
ответ дан 30 November 2019 в 00:51
поделиться

Я выполнял только автоматизацию Excel, но сталкивался с аналогичными проблемами. Ссылаясь на старый код, последний шаг закрытия имеет строку GC.Collect ()

Эта статья также упоминает его: http://support.microsoft.com/kb/317109

2
ответ дан 30 November 2019 в 00:51
поделиться

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

0
ответ дан 30 November 2019 в 00:51
поделиться

Вы пробовали изменить

oWord.Visible = False

на

oWord.Visible = True

?

Я спрашиваю, потому что Word может просить вас сделать что-то, связанное с этим шаблон, который вы пытаетесь использовать. Если он думает, что отображается диалоговое окно, он обычно не закрывается. IIRC, есть способ сделать Quit, чтобы он принудительно выходил и не ждал никаких диалогов. Но это было давно.

4
ответ дан 30 November 2019 в 00:51
поделиться

Хотя это 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 полезен для очистки любых ресурсов, выделенных в блоке 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
ответ дан 30 November 2019 в 00:51
поделиться

Попробуйте вызвать GC.WaitForPendingFinalizers() и использовать Marshal.FinalReleaseComObject вместо Marshal.ReleaseComObject. Это избавит вас от необходимости выполнять цикл.

Обновите свой код и попробуйте (вызовы GC специально находятся в начале):

GC.Collect()
GC.WaitForPendingFinalizers()

oDoc.Close()
Marshal.FinalReleaseComObject(oDoc)

Marshal.FinalReleaseComObject(oDocuments)

oWord.Quit()
Marshal.FinalReleaseComObject(oWord)

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

2
ответ дан 30 November 2019 в 00:51
поделиться

У меня возникла та же проблема, когда я это делал:

object missing = System.Reflection.Missing.Value;
wordApplication.Quit(ref missing, ref missing, ref missing);

Я решил так:

object objFalse = false;
wordApplication.Quit(ref objFalse, ref objFalse, ref objFalse);

Не спрашивайте меня, почему автоматизация офиса приключение :)

4
ответ дан 30 November 2019 в 00:51
поделиться

(Все мои советы адаптированы из этого ответа о взаимодействии с Excel.)

Здесь есть несколько важных вещей:

1) Никогда не используйте 2 точки на одной линии. Также считайте индексатор точкой

Хорошо

Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(/*...*/);

ПЛОХО

Word.Document aDoc = wordApp.Documents.Open(/*...*/);

2) Освободите все ваши указатели.

3) Нет, действительно, вернитесь и отпустите все свои указатели, вы где-то пропустили один (или, по крайней мере, я всегда так делаю).

Вот полный пример того, что НАКОНЕЦ сработало для меня в одном проекте после долгих стенаний и скрежета зубами:

object m = Missing.Value;
// this must be an object, not a string. if you forget though,
// intellisense will remind you
object oFilename = @"C:\my sheet.doc";

object readOnly = false;
object isVisible = false;

Word.Application wordApp = new Word.ApplicationClass();
wordApp.Visible = false;
// remember: don't use 2 dots on 1 line
Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(ref oFilename, ref m, ref readOnly, ref m,
    ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref isVisible,
    ref m, ref m, ref m, ref m);
aDoc.Activate();

object findText = "my old value";
object replaceText = "new and improved value";

object oTrue = true;
object oFalse = false;
object replace = 2;
object wrap = 1;

Word.Selection s = wordApp.Selection;
Word.Find f = s.Find;
f.Execute(ref findText, ref oTrue,
    ref oTrue, ref oFalse, ref oFalse,
    ref oFalse, ref oTrue, ref wrap, ref oFalse,
    ref replaceText, ref replace, ref oFalse, ref oFalse,
    ref oFalse, ref oFalse);

aDoc.SaveAs(ref oFilename, ref m, ref m, ref m, ref m, ref m, ref m,
    ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m, ref m);

object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
// casting here because intellisense complained of ambiguity
(aDoc as Word._Document).Close(ref doNotSaveChanges, ref m, ref m);

// release each in the reverse of the order in which it was first used
// ReleaseComObject might also work as well. I haven't tested yet
Marshal.FinalReleaseComObject(f);
Marshal.FinalReleaseComObject(s);
Marshal.FinalReleaseComObject(aDoc);
Marshal.FinalReleaseComObject(d);

// must quit app before releasing
// again: casting because intellisense complained of ambiguity
(wordApp as Word._Application).Quit(ref m, ref m, ref m);
Marshal.FinalReleaseComObject(wordApp);
11
ответ дан 30 November 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: