代码之家  ›  专栏  ›  技术社区  ›  knut

无法使用COM和.NET互操作从acropdf.dll实例化PDF浏览器控件

  •  1
  • knut  · 技术社区  · 14 年前

    当我尝试在C中实例化这样的PDF浏览器控件时:

    AcroPDFLib.AcroPDFClass acrobat = new AcroPDFLib.AcroPDFClass();
    

    我得到了 COMException 带着这条信息:

    由于以下错误,从iclassFactory创建clsid ca8a9780-280d-11cf-a24d-444553540000的COM组件实例失败:80004005。

    我提到过 AcROPDF.DLL 它有组件名称 Adobe Acrobat 7.0浏览器控件类型库1.0 .

    当我运行Visual C 2008速成版时 管理员 我收到另一条错误消息:

    无法将“acropdflib.acropdfclass”类型的COM对象强制转换为接口类型“acropdflib.iacroaxdocshim”。此操作失败,因为IID为“3B813CE7-7C10-4F84-AD06-9DF76D97A9AA”的接口的COM组件上的queryInterface调用由于以下错误而失败:不支持此类接口(来自hresult的异常:0x80004002(e_no interface))。

    当我尝试使用对象时,在下一行发生这种情况:

    acrobat.LoadFile("book.pdf");
    

    我不知道怎么了。最感激的帮助!

    2 回复  |  直到 14 年前
        1
  •  4
  •   Simon P Stevens    14 年前

    .NET COM互操作不会将所有COM消息直接路由回调用方。如果你从一个STA打电话给COM,它将无法理解你的应用程序如何处理重新进入。这意味着可以通过重试处理的失败消息最终会导致异常。

    尝试实施 IMessageFilter 接口。这将允许COM了解如何将消息传回您的应用程序。尤其是,实施 RetryRejectedCall 并检查故障是否标志并可能返回超时值(比如1000毫秒),以允许COM在短暂暂停后重试。

    它是一个COM类型,因此这是定义接口所需的代码:

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000016-0000-0000-C000-000000000046")]
    public interface IMessageFilter
    {
        [PreserveSig]
        int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo);
    
        [PreserveSig]
        int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);
    
        [PreserveSig]
        int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);
    }
    

    这是您将如何实现它的一个示例:

    public class MyMessageFilter : IMessageFilter
    {
        int IMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller,int dwTickCount, IntPtr lpInterfaceInfo)
        {
            // 0 means that it's handled.
            return 0;
        }
    
        int IMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
        {
            // The return value is the delay (in ms) before retrying.
            return 1000;
        }
    
        int IMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
        {
            // 1 hear means that the message is still not processed and to just continue waiting.
            return 1;
        }
    }
    

    一旦实现了消息过滤器,就需要使用 CoRegisterMessageFilter . 这是每个线程的注册,因此请注意您正在调用它的线程。这个 PInvoke signiture is :

    [DllImport("ole32.dll")]
    static extern int CoRegisterMessageFilter(IMessageFilter lpMessageFilter, out IMessageFilter lplpMessageFilter);
    

    即使这不起作用,至少,如果你把所有的消息都记录在过滤器中,你应该希望得到更多关于问题的信息。查看传递到消息过滤器中的参数值。如果您查找它们,它们将与错误/状态代码相关。

    [请注意,我指的IMessageFilter与 System.Windows.Forms.IMessageFilter ,因此请确保不会意外使用WinForms One。]

        2
  •  2
  •   knut    14 年前

    以下是使用Adobe PDF Reader控件的步骤:

    1. 创建新的Windows窗体应用程序: 文件→新建项目…→Windows窗体应用程序→确定
    2. 添加对Adobe Acrobat 7.0浏览器控件类型库1.0的引用: 项目→添加引用…→COM→Adobe Acrobat 7.0浏览器控件类型库1.0→确定
    3. 将Adobe PDF Reader控件添加到工具箱: 工具→选择工具箱项…→COM组件→Adobe PDF Reader→确定
    4. 将Adobe PDF Reader控件从工具箱拖到表单中

    我不知道为什么,但我必须以管理权限运行Microsoft Visual C_2008速成版才能使其正常工作。对于有限的用户,我在设计器中收到以下消息:

    错误hresult e_fail已从对COM组件的调用中返回。

    请注意,将Adobe PDF Reader控件添加到工具箱后,已使用名称创建了新的.NET互操作程序集。 axinterop.acropdflib.dll文件 . 已将对此新程序集的引用添加到项目引用中。

    Adobe PDF Reader控件的API参考文档位于以下位置: http://icio.us/ajukkr

    这个论坛主题提供了一些更有用的信息: http://forums.adobe.com/thread/438362