几乎在所有情况下都可以创建新的VSTO Word应用程序。我用这一行来创建一个新实例:
var wordApplication = new Application {Visible = false}
(应用程序是" Microsoft.Office.Interop.Word.Application")
我们在单元测试和一些自动化中做了很多。但是在大约1000次调用中一次或两次,初始化没有完成并且进程挂起。 (任何人都知道原因吗?)
要解决这个问题,我将实例化包装成超时并再次尝试:
var wordApplication = Utilities.CallWithTimeout(
// stuff to do
() => new Application {Visible = false},
// error handler before the TimeoutException happens
() =>
{
var info = "Try to create a WordApplication failed after 15 seconds";
Tracer.TraceEvent(TraceEventType.Error, info, TraceCategory.Application);
KillWordApplicationOnError(before);
},
// timeout
TimeSpan.FromSeconds(15));
(CallWithTimeout:https://gist.github.com/JuergenGutsch/b4b72fcb6a06327a6a41使用此方法重试:https://gist.github.com/JuergenGutsch/219e9fe3e5aad1a098f3)
我们通过识别单词process并终止该进程来杀死应用程序。请记住,因为实例化暂停,我们没有Word应用程序来使用Quit(),但winword.exe进程正在运行,我们需要将其杀死。 (我们如何杀死这个过程:https://gist.github.com/JuergenGutsch/92b64117cf51c15bab83)
这解决了挂起过程中的问题,我们得到了一个新问题,在大约3000次调用中发生一次或两次。新问题是一个安全问题,它会禁用一个到所有Word加载项,以及一些包含VBA宏的自定义dotm模板。
我们没有得到任何例外,我们也没有在事件日志中获得任何条目。在杀死过程之后,除了这一个:
An exception of type 'System.Runtime.InteropServices.COMException' occurred in BIS.MEDCS.Connectivity.Word.VSTO.dll but was not handled in user code
Additional information: Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
但是这个异常是通过重试来处理的,实例化可以用于下一次尝试。
你们中有谁知道这里发生了什么吗?
答案 0 :(得分:1)
除了@Eugene之外,垃圾收集不是“立即”发生,而是“最佳机会”,你可能会看到清理运行实例的速度变慢(特别是如果COM对象没有正确发布)
强制执行垃圾收集:
GC.Collect
GC.WaitForPendingFinalizers
GC.Collect
GC.WaitForPendingFinalizers
就像抬头一样,副本不是错误,它是由.NET对象存储在内存中的方式完成的,所以你需要执行两次Collect和WaitForPendingFinalizers。
所以首先要确保你自己释放你的物品,并在最后的手段收集垃圾。
答案 1 :(得分:0)
您需要立即释放基础COM对象。完成使用后,使用System.Runtime.InteropServices.Marshal.ReleaseComObject释放Word对象。然后在Visual Basic中将变量设置为Nothing(C#中为null)以释放对该对象的引用。请在Systematically Releasing Objects文章中详细了解相关内容。本文与OUtlook相关,但相同的规则可以应用于包括Word在内的所有Office应用程序。
在内存中保留COM对象(不减少引用计数器)可能会导致进程在主机关闭后继续运行。