当我尝试在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 Express Edition时,我收到另一条错误消息:
无法将“AcroPDFLib.AcroPDFClass”类型的COM对象强制转换为接口类型“AcroPDFLib.IAcroAXDocShim”。此操作失败,因为IID为“{3B813CE7-7C10-4F84-AD06-9DF76D97A9AA}”的接口的COM组件上的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))
当我尝试使用该对象时,会发生在下一行:
acrobat.LoadFile("book.pdf");
我无法弄清楚出了什么问题。非常感谢!
答案 0 :(得分:4)
.net COM interop不会将所有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。]
答案 1 :(得分:2)
以下是使用Adobe PDF Reader控件的步骤:
我不确定为什么,但我必须运行具有管理权限的Microsoft Visual C#2008 Express Edition才能使其正常运行。对于有限的用户,我在设计师中收到此消息:
错误HRESULT E_FAIL已从调用COM组件返回。
请注意,在将Adobe PDF Reader控件添加到工具箱后,已创建名为 AxInterop.AcroPDFLib.dll 的新.NET互操作程序集。对您的项目引用添加了对此新程序集的引用。
Adobe PDF Reader控件的API参考文档位于:http://icio.us/ajukkr
此论坛主题提供了一些更有用的信息:http://forums.adobe.com/thread/438362