Word 自动化 InvalidCastException RPC / COM 异常

tom*_*omo 2 com automation rpc ms-word exception

我正在开发 Word 自动化应用程序,但遇到了意外的 RPC/COM 转换异常的严重问题

[System.InvalidCastException: Nie mo?na rzutowa? obiektu modelu COM typu 'System.__ComObject' na typ interfejsu 'Microsoft.Office.Interop.Word._Application'。Ta operacja nie powiod?a si?, poniewa? wywo?anie metody QueryInterface dla sk?adnika modelu COM w celu uzyskania interfejsu o identyfikatorze IID '{00020970-0000-0000-C000-000000000046}' nie?siwiod? z powodu nast?puj?cego b??du: Serwer RPC jest niedost?pny。(Wyj?tek od HRESULT:0x800706BA)。]

从波兰语翻译成英语:

无法将 System.__ComObject 转换为 Microsoft.Office.Interop.Word._Application。原因是 IID '{00020970-0000-0000-C000-000000000046}' 的 QueryInterface 失败 - RPC 服务器不可用 - 错误代码 HRESULT: 0x800706BA

这里是wordapp模块的简介:

初始化 - 用户登录后。

using Microsoft.Office.Interop.Word;

    public class WordApp       
    {
        Application app = null;
        object m = System.Reflection.Missing.Value; 
        object oFalse = false;  
        object oTrue = true;
Run Code Online (Sandbox Code Playgroud)

....

            app = Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application.12")) as Application;
            app.Visible = false;
            app.DisplayAlerts = WdAlertLevel.wdAlertsNone;
            app.PrintPreview = false;
Run Code Online (Sandbox Code Playgroud)

我正在使用 Activator.CreateInstance 而不是 app = new Application() - 这里是解释

然后用户可以在 wordapp 模块中执行 2 个操作

a) 打印准备好的 docx 文档

        System.Windows.Forms.PrintDialog pd = new System.Windows.Forms.PrintDialog();
        ...

        this.app.ActivePrinter = pd.PrinterSettings.PrinterName;
        object oNumcopies = pd.PrinterSettings.Copies;
        object oRange = WdPrintOutRange.wdPrintAllDocument;
        object inputname = fullPath;
        Document doc = app.Documents.Add(
                              ref inputname,
                              ref m,
                              ref m,
                              ref m);
        try
        {
            // Print the document 
            doc.PrintOut(ref oFalse, ref oFalse, ref oRange,
                    ref m, ref m, ref m,
                    ref m, ref oNumcopies, ref m, ref m,
                    ref oFalse, ref m, ref m,
                    ref m, ref m, ref m, ref m,
                    ref m);
        }
        finally
        {
            doc.Close(ref oFalse, ref m, ref m);
            doc = null;
        }
Run Code Online (Sandbox Code Playgroud)

b) 将 docx 转换为 mht

        object inputname = docxname;
        object outputname = htmlname;
        object fileType = WdSaveFormat.wdFormatWebArchive;

        Document doc = app.Documents.Add( 
                              ref inputname,
                              ref m,
                              ref m,
                              ref m);
        try
        {
            doc.SaveAs(ref outputname, ref fileType,
                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);
        }
        finally
        {
            doc.Close(ref oFalse, ref m, ref m);
            doc = null;
        }
Run Code Online (Sandbox Code Playgroud)

当用户注销时,然后我释放单词实例:

            object oSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
            app.Quit(
         ref oSaveChanges,
         ref m,
         ref m);
Run Code Online (Sandbox Code Playgroud)

异常会在随机的地方抛出 - 但最常见的地方是在 app.Documents.Add 附近。在那个异常之后,app.Quit 是不可能的。似乎这个词实例已经死了。

我在事件日志(应用程序范围)中发现了那个东西:

事件类型 offdiag12, P1 585d8a02-f370-4c04-85b6-fccad7e80459255ec053-6dbd-4a22-9e59-112a79de8c6a, P2 NIL, P3 NIL, P4 NIL, P5 NIL, P5 NIL, P5 NIL, P5

我运行了 office 诊断程序,但没有发现任何错误。

是否可以从系统中启用/查找更多错误信息?

这段代码在我的开发机器(vista)上运行得很好。该问题发生在客户机器上(通常是 winxp sp2/sp3)。

我的代码中有错误还是什么?

我唯一需要补充的一件事。WordModule init/close/print 函数从主线程调用,savetomht 从后台工作线程调用。

sha*_*oth 5

你所描述的,往往是指以下情况。您使用 COM out-proc 服务器(在单独的进程中实例化的 COM 对象,而不是在与您的程序相同的进程中)并且由于某种原因,COM 服务器遇到致命错误并意外终止。您使用的 COM 对象不再存在。由于 RPC 用于与 out-proc COM 服务器进行交互,并且在终止后服务器端不再存在,您会收到错误消息,指出 RPC 服务器不可用,这是真的,但看起来很混乱。

您必须研究并消除 COM 服务器终止的原因。最可能的原因如下:

  • 您传递给调用的一些不合理的输入值和
  • 事件处理程序中未处理的异常。如果您对从 COM 组件触发的事件进行任何处理,您应该捕获可能在处理程序内部抛出的所有异常,并且不要让它们传播到处理程序外部。