How to diagnose cause, fix, or work around Adobe ActiveX / COM related error 0x80004005 progmatically?
Asked Answered
S

3

8

I've built a C# .NET app that uses the Adobe ActiveX control to display a PDF.

It relies on a couple DLLs that get shipped with the application. These DLLs interact with the locally installed Adobe Acrobat or Adobe Acrobat Reader installed on the machine.

This app is being used by some customer already and works great for nearly all users ( I check to see that the local machine is running at least version 9 of either Acrobat or Reader already ).

I've found 3 cases where the app returns the error message "Error HRESULT E_FAIL has been returned from a call to a COM component" when trying to load (when the activex control is loading).

I've checked one of these user's machines and he has Acrobat 9 installed and is using it frequently with no problems. It does appear that Acrobat 7 and 8 were installed at one time since there are entries for them in the registry along with Acrobat 9.

I can't reproduce this problem locally, so I am not sure exactly which direction to go.

The error at the top of the stacktrace is: System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.

Some research into this error indicates it is a registry problem.

Does anyone have a clue as to how to fix or work around this problem, or determine how to get to the core root of the problem?

The full content of the error message is this:

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)

Spoofery answered 26/3, 2010 at 19:52 Comment(12)
Could it be 32bit/64bit issue, that the OS is 64bit while the Adobe dll's are 32bit.Agaric
"Some research into this error indicates it is a registry problem." Test that hypothesis. Get RegMon, or ProcMon or whatever they're calling that thing nowadays and see whether the registry accesses are as you'd expect them to be given that someone is trying to cocreate a COM object.Waterlogged
I am not familiar with how to do what you are suggesting... - how do I 'see whether the registry accesses are as you'd expect them to be given that someone is trying to cocreate a COM object.' once running ProcMon or similar? - I'd like to figure it out ahead of attempting it on the user's machine since I have limited access to their machine.Spoofery
My comment on the registry problem comes from "error-fix-tool.com/errors.php?t=0X80040005"Spoofery
Mikael: This user's machine was WindowsXP, so I don't think it is a 64bit issue.Spoofery
I saw similar problems to yours when using Acrobat's ActiveX control. I had enough of them that I eventually bailed on PDF and used XPS instead. In my experience, though, Acrobat8 was the most reliable for use by Applications. I was considering shipping the v8 DLLs with my product, except that it would violate the Adobe license. Also the older v8 is known insecure. So in the end I just threw up my hands and went to a different page description language. WPF, XAML, and XPS worked fine.Astragal
Cheeso: thanks for the input.. however the source files for this cataloging system are already in PDF and the scope of the project doesn't include converting everything to another format, at this point.Spoofery
Eric: Any clue how to make use of the ProcMon tool once I run it to take advantage of your suggestion? I am new to the tool and its a bit like drinking from a firehose at this point. I've tried filtering out all except registry entries and only on items with process name equal to my app. I still get bunch of entries and not exactly sure what to look for on my machine that would be equivalent to when I diagnose the problem on the problematic machine - will I see a flag or specific 'RESULT' ?Spoofery
Somehow the operating system needs to go from having nothing more than a CLSID and an IID to having a brand new object up and running and the right interface pointer returned. It does that by first converting the CLSID to a string, then looking that up in the registry to get the PROGID, then looking up the PROGID in the registry to get the DLL name. So I would start there. Are those registry entries looked up successfully?Waterlogged
I see... I am not sure which DLL is giving the problem per se. Not sure if it is the DLLs I include or the ones they interact with on the local machine (i.e. the Acrobat installed DLLs). I suppose I should track using ProcMon from the ProcessName of my app and see where it fails compared with a machine it works on? Also, could it be that the Adobe ActiveX DLLs I am including with my app are not registered? If so, why would my app and the dlls work with no registration, no problem, on 99% of the machines it runs on (xp, vista, or 7) but fail on just a few machines?Spoofery
I've run the procmon on the machine where the error message is generated from the process, filtering on the process name. Each time it fails the last message generated (when the dialog box is displayed) is when accessing C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\OLEAUT32.dll (which doesn't exist)... Other attempts to access other locations for OLEAUT32.dll also occur in the events log. Not sure if the actual problem is coming from an event that right after this? Or if this event is actually form the dialog box opening and not what is generating the error. Not sure how to interpret.Spoofery
Is there any way to query what DLL is attempted to be called when this error occurs?: System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has beenSpoofery
S
12

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?
Spoofery answered 1/4, 2010 at 16:30 Comment(2)
Also worth noting that if Adobe Pro is installed, the option is disabled in Adobe Reader, and must be enabled from Adobe Pro.Zodiac
Updating this 5 years later now with a reference to a new question I posted here #31255983 because the solution I posted here 5 years ago isn't working as expected in XI or DC. The bBrowserIntegration key appears to be deprecated in 11. Does anyone know the XI (11) or DC equivalent of my previous solution (coded not manual)?Spoofery
A
1

For my system (Windows XP, Adobe Reader 9.3.2) your solution didn't work (but gave me enough inspiration, THANK YOU!!)

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'");
        }
}
Alkalinize answered 30/4, 2010 at 8:59 Comment(0)
I
0

Thank you so much!

I just want to add that I am able to reproduce the behaviour with Adobe Reader XI too. (Windows XP 32 bit - VB.net 2005.)

The registry key is(*):

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

If that key value is 1, the activex component is correctly instantiated. If that key value is 0, I get the exception at form instantiation.

I was not able to find the browser integration option in Adobe Reader XI Internet properties page.

(*) I found that value on this page: http://forums.adobe.com/thread/1042774

Igraine answered 27/3, 2013 at 10:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.