创建VSTO Word应用程序时出现问题

时间:2016-02-23 14:50:36

标签: c# ms-word vsto ms-office office-interop

几乎在所有情况下都可以创建新的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)).

但是这个异常是通过重试来处理的,实例化可以用于下一次尝试。

你们中有谁知道这里发生了什么吗?

2 个答案:

答案 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对象(不减少引用计数器)可能会导致进程在主机关闭后继续运行。