Kei*_*ith 20 .net com interop ms-word office-interop
我遇到了经典场景,当在.NET中创建Word COM对象时(通过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()
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在创建和正确处理对象,甚至采取额外的步骤来循环Marsha.ReleaseComObject,直到它返回正确的代码.在其他方面使用Word对象很好,只是那些讨厌的Documents.Add让我感到悲伤.是否有另一个在此过程中创建的对象需要引用和处理?我需要遵循另一个处理步骤吗?别的什么?非常感谢您的帮助 :)
Update: 我在处理步骤结束时尝试了GC.Collect,但仍然没有运气.
Update 2: 我已经将问题缩小到使用自定义模板.当我调用Documents.Add(...)时,我为新文档指定了一个自定义模板.如果我不这样做而是调用没有参数的Add(),那么问题就不会发生.
Din*_*nah 11
(我的所有建议都是根据这个关于Excel互操作的答案改编的.)
这里有一些重要的事情:
1)切勿在同一条线上使用2个点.还要将索引器视为点
好
Word.Documents d = wordApp.Documents;
Word.Document aDoc = d.Open(/*...*/);
Run Code Online (Sandbox Code Playgroud)
坏
Word.Document aDoc = wordApp.Documents.Open(/*...*/);
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
我发现使用自定义模板时使用 Documents.Add()是罪魁祸首。我无法解释为什么这会让 WinWord.exe 挂起。但是,还有其他方法可以从模板创建文档,但不会导致相同的问题。
所以我更换了:
Dim doc As Word.Document = documents.Add(Template:=CObj(templatePath))
Run Code Online (Sandbox Code Playgroud)
和:
Dim doc As Word.Document = documents.Add()
doc.AttachedTemplate = templatePath
doc.UpdateStyles()
Run Code Online (Sandbox Code Playgroud)
使用 AttachedTemplate 指定模板对我有用,并且不会让 WinWord.exe 挂起。
(然而,出现了一个新问题......使用 AttachedTemplate/UpdateStyles 时,模板页脚中的图像不会复制到文档中。我将其作为一个单独的问题来解决。但由于此方法解决了我原来的问题,我很满意。感谢所有提供答案的人!)
| 归档时间: |
|
| 查看次数: |
23207 次 |
| 最近记录: |