7

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

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

这个应用程序已经被一些客户使用,并且几乎适用于所有用户(我检查本地计算机是否已经运行至少版本 9 的 Acrobat 或 Reader)。

我发现 3 种情况,应用程序在尝试加载时(在加载 activex 控件时)返回错误消息“错误 HRESULT E_FAIL 已从对 COM 组件的调用中返回”。

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

我无法在本地重现此问题,因此我不确定该往哪个方向发展。

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

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

是否有人知道如何解决或解决此问题,或确定如何找到问题的核心根源?

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

System.Runtime.InteropServices.COMException (0x80004005):调用 COM 组件时返回错误 HRESULT E_FAIL。在 System.Windows.Forms.CreateWithoutLicense(Guid clsid) 在 System.Windows.Forms.AxHost.CreateWithLicense 的 System.Windows.Forms.UnsafeNativeMethods.CoCreateInstance(Guid 和 clsid,对象 punkOuter,Int32 上下文,Guid 和 iid)(字符串许可证, Guid clsid) 在 System.Windows.Forms.AxHost.CreateInstanceCore(Guid clsid) 在 System.Windows.Forms.AxHost.CreateInstance() 在 System.Windows.Forms.AxHost.GetOcxCreate() 在 System.Windows.Forms.AxHost .TransitionUpTo(Int32 state) 在 System.Windows.Forms.AxHost.CreateHandle() 在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) 在 System.Windows.Forms.Control。

4

3 回答 3

11

Ok, reporting back to answer my own question.

The problem was directly related to the setting for 'Display PDF in browser' in Preferences > Internet. With this option checked, the problem goes away. When it is unchecked, it comes back.

Here is how we propose to handle it programmatically:

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

A few items to note:

Does anyone know if these locations are interchangeable in all versions or if based on specific versions of Acrobat the registry key is in different locations? Does Reader follow the same logic as Acrobat?

  • Does Adobe use any other method to determine the 'default Adobe application for opening PDF files' other than the windows file association? I ask because if you have a non-adobe product, such as FoxIt installed as the default file association application, but are using the ActiveX control for Adobe on a machine that has both Reader and Acrobat installed, what logic is used to decide which application the COM object will talk to?
于 2010-04-01T16:30:59.503 回答
1

对于我的系统(Windows XP、Adobe Reader 9.3.2),您的解决方案不起作用(但给了我足够的灵感,谢谢!!)

private void browserIntegration(string defaultPdfProgram)
    {
        try
        {
            RegistryKey reader = null;
            string[] vers = null;

            #region Walters Versuch
            reader = Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Adobe");
            reader = reader.OpenSubKey("Acrobat Reader");
            vers = reader.GetSubKeyNames();
            if (vers.Contains<string>("9.0"))
            {
                reader = reader.OpenSubKey("9.0");
                reader = reader.OpenSubKey("Originals", true);
                if (reader.GetValueNames().Contains<string>("bBrowserIntegration"))
                    reader.SetValue("bBrowserIntegration", 1, RegistryValueKind.DWord);
                // wenn der Key fehlt ist Browserintegration auch angeschaltet
                // alternativ: reader.DeleteSubKey("bBrowserIntegration", false);
            }
            else
                MessageBox.Show(
                    "In case you run into problems later, please make sure yourself to select\n'Show PDF in Browser' in Acrobat Reader's Settings"
                    , "Unknown Version of Acrobat Reader");

            #endregion
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message + "\n" + ex.StackTrace
                + "\nIn case you run into problems later, please make sure yourself to select\n'Show PDF in Browser' in Acrobat Reader's Settings"
                , "Error while switching on 'Browserintegration' in 'Acrobat Reader'");
        }
}
于 2010-04-30T08:59:30.030 回答
0

太感谢了!

我只想补充一点,我也可以使用 Adob​​e Reader XI 重现该行为。(Windows XP 32 位 - VB.net 2005。)

注册表项是(*):

HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\11.0\Originals\bBrowserIntegration

如果该键值为 1,则正确实例化了 activex 组件。如果该键值为 0,我会在表单实例化时遇到异常。

我无法在 Adob​​e Reader XI Internet 属性页面中找到浏览器集成选项。

(*) 我在此页面上找到了该值: http ://forums.adobe.com/thread/1042774

于 2013-03-27T10:52:31.033 回答