2

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

[System.InvalidCastException: Nie można rzutować obiektu modelu COM typu 'System.__ComObject' na typ interfejsu 'Microsoft.Office.Interop.Word._Application'。Ta Operacja NiePowiodłaSićżpż威沃韦·莫德QueryInterface DLASkładnikaModelu Com Com C Com Com Com o IdentyFikatorze IID'{00020970-000000C46}'NiePowiodłoSięZPOWODUNASTęPUJİCOGŁęDU:Serwer RPC jestniedostę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;

……

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

我使用的是 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;
        }

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;
        }

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

            object oSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
            app.Quit(
         ref oSaveChanges,
         ref m,
         ref m);

异常会在随机位置抛出 - 但最常见的位置是 app.Documents.Add 附近。在该异常之后,无法 app.Quit。看来这个词实例已经死了。

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

EventType offdiag12, P1 585d8a02-f370-4c04-85b6-fccad7e80459255ec053-6dbd-4a22-9e59-112a79de8c6a, P2 NIL, P3 NIL, P4 NIL, P5 NIL, P6 NIL, P7 NIL, P8 NIL, P9 NIL, P10 NIL。

我运行办公室诊断,它没有发现任何错误。

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

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

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

我需要添加的唯一一件事。WordModule init/close/print 函数从主线程调用,savetomht 从 backgroundworkders 线程调用。

4

2 回答 2

5

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

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

  • 您传递给调用的一些不合理的输入值和
  • an unhandled exception in an event handler. If you have any handling for events fired from a COM component you should catch all the exceptions that may be thrown inside your handler and not let them propagate outside the handler.
于 2009-03-27T05:08:14.173 回答
1

我不知道,但这里有一些基于一般经验的建议。您可能会尝试使用 distinct ms 而不是在所有参数之间共享一个(想法是,如果值在内部被弄乱,则可能会产生不可预测的结果)。您可能还想尽可能提供合理的值(而不是ms)。API 的某些版本可能比其他版本更宽容。

于 2009-03-26T17:43:11.963 回答