1

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

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

我收到一条COMException消息:

由于以下错误,从 IClassFactory 创建具有 CLSID {CA8A9780-280D-11CF-A24D-444553540000} 的 COM 组件实例失败:80004005。

我参考了AcroPDF.dll,它的组件名称为 Adob​​e Acrobat 7.0 Browser Control Type Library 1.0

当我以管理员身份运行 Visual C# 2008 Express Edition 时,我收到另一条错误消息:

无法将“AcroPDFLib.AcroPDFClass”类型的 COM 对象转换为接口类型“AcroPDFLib.IAcroAXDocShim”。此操作失败,因为 IID 为“{3B813CE7-7C10-4F84-AD06-9DF76D97A9AA}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(HRESULT 异常:0x80004002 (E_NOINTERFACE)) .

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

acrobat.LoadFile("book.pdf");

我不知道出了什么问题。帮助最感激!

4

2 回答 2

4

.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 签名是:

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

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

[请注意,我在这里指的 IMessageFilter 与System.Windows.Forms.IMessageFilter不同,因此请确保您不会意外使用winforms。]

于 2010-04-23T22:02:32.013 回答
3

以下是使用 Adob​​e PDF Reader 控件的步骤:

  1. 创建一个新的 Windows 窗体应用程序:文件 → 新建项目... → Windows 窗体应用程序 → 确定
  2. 添加对 Adob​​e Acrobat 7.0 Browser Control Type Library 1.0 的引用:Project → Add Reference... → COM → Adob​​e Acrobat 7.0 Browser Control Type Library 1.0 → OK
  3. 将 Adob​​e PDF Reader 控件添加到工具箱:工具 → 选择工具箱项目... → COM 组件 → Adob​​e PDF Reader → 确定
  4. 将 Adob​​e PDF Reader 控件从您的工具箱拖到表单中

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

对 COM 组件的调用已返回错误 HRESULT E_FAIL。

请注意,将 Adob​​e PDF Reader 控件添加到您的工具箱后,已创建一个名为AxInterop.AcroPDFLib.dll的新 .NET 互操作程序集。对这个新程序集的引用已添加到您的项目引用中。

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

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

于 2010-04-24T13:49:45.710 回答