c# - 如何以编程方式诊断原因、修复或解决与 Adob​​e ActiveX/COM 相关的错误 0x80004005?

标签 c# .net com dll acrobat

我构建了一个使用 Adob​​e ActiveX 控件来显示 PDF 的 C# .NET 应用程序。

它依赖于应用程序随附的几个 DLL。 这些 DLL 与本地安装的 Adob​​e Acrobat 或机器上安装的 Adob​​e Acrobat Reader 交互。

这个应用程序已经被一些客户使用并且对几乎所有用户都很好用(我检查本地机器是否已经运行至少第 9 版的 Acrobat 或 Reader)。

我发现了 3 种情况,应用程序在尝试加载时(正在加载 activex 控件时)返回错误消息“Error HRESULT E_FAIL has been returned from a call to a COM component”。

我检查了其中一个用户的机器,他安装了 Acrobat 9 并且经常使用它,没有任何问题。似乎 Acrobat 7 和 8 是同时安装的,因为注册表中有它们的条目以及 Acrobat 9。

我无法在本地重现这个问题,所以我不确定到底该往哪个方向走。

堆栈跟踪顶部的错误是:System.Runtime.InteropServices.COMException (0x80004005):调用 COM 组件返回错误 HRESULT E_FAIL。

对此错误的一些研究表明这是一个注册表问题。

有没有人知道如何解决或解决这个问题,或者确定如何找到问题的核心根源?

错误信息的完整内容是这样的:

System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.    at System.Windows.Forms.UnsafeNativeMethods.CoCreateInstance(Guid& clsid, Object punkOuter, Int32 context, Guid& iid)    at System.Windows.Forms.AxHost.CreateWithoutLicense(Guid clsid)    at System.Windows.Forms.AxHost.CreateWithLicense(String license, Guid clsid)    at System.Windows.Forms.AxHost.CreateInstanceCore(Guid clsid)    at System.Windows.Forms.AxHost.CreateInstance()    at System.Windows.Forms.AxHost.GetOcxCreate()    at System.Windows.Forms.AxHost.TransitionUpTo(Int32 state)    at System.Windows.Forms.AxHost.CreateHandle()    at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)    at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)    at System.Windows.Forms.AxHost.EndInit()    at AcrobatChecker.Viewer.InitializeComponent()    at AcrobatChecker.Viewer..ctor()    at AcrobatChecker.Form1.btnViewer_Click(Object sender, EventArgs e)    at System.Windows.Forms.Control.OnClick(EventArgs e)    at System.Windows.Forms.Button.OnClick(EventArgs e)    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)    at System.Windows.Forms.Control.WndProc(Message& m)    at System.Windows.Forms.ButtonBase.WndProc(Message& m)    at System.Windows.Forms.Button.WndProc(Message& m)    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

最佳答案

好的,报告回来回答我自己的问题。

问题与首选项 > Internet 中“在浏览器中显示 PDF”的设置直接相关。 选中此选项后,问题就消失了。取消选中时,它会返回。

以下是我们建议如何以编程方式处理它:

    private string defaultPdfProg()
    { //Returns the default program for opening a .pdf file; On Fail returns empty string. 
      // (see notes below) 
        string retval = "";

        RegistryKey pdfDefault = Registry.ClassesRoot.OpenSubKey(".pdf").OpenSubKey("OpenWithList");
        string[] progs = pdfDefault.GetSubKeyNames();
        if (progs.Length > 0)
        {
            retval = progs[1];
            string[] pieces = retval.Split('.'); // Remove .exe

            if (pieces.Length > 0)
            {
                retval = pieces[0];
            }
        }

        return retval;
    }

    private void browserIntegration(string defaultPdfProgram)
    { //Test if browser integration is enabled for Adobe Acrobat (see notes below)
        RegistryKey reader = null;
        string[] vers = null;

        if (defaultPdfProgram.ToLower() == "acrobat")
        { //Default program is Adobe Acrobat
            reader = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Adobe").OpenSubKey("Adobe Acrobat");
            vers = reader.GetSubKeyNames();
        }
        else if (defaultPdfProgram.ToLower() == "acrord32")
        { //Default program is Adobe Acrobat Reader
            reader = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Adobe").OpenSubKey("Acrobat Reader");
            vers = reader.GetSubKeyNames();
        }
        else
        {
            //TODO: Handle non - adobe .pdf default program
        }

        if (vers.Length > 0)
        {
            string versNum = vers[vers.Length - 1].ToString();
            reader = reader.OpenSubKey(versNum);
            reader = reader.OpenSubKey("AdobeViewer",true);

            Boolean keyExists = false;
            Double keyValue = -1;
            foreach(string adobeViewerValue in reader.GetValueNames())
            {
                if (adobeViewerValue.Contains("BrowserIntegration"))
                {
                    keyExists = true;
                    keyValue = Double.Parse(reader.GetValue("BrowserIntegration").ToString());
                }
            }

            if (keyExists == false || keyValue < 1)
            {
                string message = "This application requires a setting in Adobe to be changed. Would you like to attempt to change this setting automatically?";
                DialogResult createKey = MessageBox.Show(message, "Adobe Settings", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                if (createKey.ToString() == "OK")
                {
                    reader.SetValue("BrowserIntegration", 1, RegistryValueKind.DWord);
                    //test to make sure registry value was set
                }
                if (createKey.ToString() == "Cancel")
                {
                    //TODO: Provide instructions to manually change setting
                }
            }
        }
    }

需要注意的几点:

有谁知道这些位置是否在所有版本中都可以互换,或者注册表项是否基于 Acrobat 的特定版本位于不同位置? Reader 是否遵循与 Acrobat 相同的逻辑?

  • 除了 Windows 文件关联之外,Adobe 是否使用任何其他方法来确定“用于打开 PDF 文件的默认 Adob​​e 应用程序”?我问是因为如果您有非 adobe 产品,例如 FoxIt 作为默认文件关联应用程序安装,但在同时安装了 Reader 和 Acrobat 的机器上使用 Adob​​e 的 ActiveX 控件,则使用什么逻辑来决定哪个应用程序COM 对象将与之对话?

关于c# - 如何以编程方式诊断原因、修复或解决与 Adob​​e ActiveX/COM 相关的错误 0x80004005?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2526301/

相关文章:

c# - 64 位进程不支持 Explorer OM

c++ - 我怎么能只允许 flash activeX 而其他人不允许在我的 webcontrol 中使用 IWebBrowser2?

c# - 如何使用 C# 可靠地检查是否启用了 Windows 更新?

c# - 为什么 localloc 会破坏这个 CIL 方法?

c# - 如果首先使用 EF 核心代码映射不存在,则会出现错误

javascript - 主题标签的正则表达式一开始在 C# 中不起作用,但在 Javascript 中起作用

.NET:Thread 类怎么会被滥用,它不是密封的吗?

c# 模拟接口(interface) vs 模拟类

c - 对 CLSID_MMDeviceEnumerator 和 IID_IMMDeviceEnumerator 的 undefined reference

c# - 将表单列表存储在数组中