使用E_NOINTERFACE将mshtml.IHTMLImgElement强制转换为mshtml.IHTMLElementRender失败

时间:2013-06-04 12:49:20

标签: c# .net internet-explorer com-interop mshtml

我有C#.NET 4 WinForms应用程序(使用MSHTML 7),它启动新的并连接到现有的IE 10实例。它遍历所有图像并下载它们进行操作。由于图像已经由IE下载,因此这种方法既费时又多余。

我到处搜索过,只有少数论坛讨论过这个主题,但是所有人都可以将mshtml.IHTMLImgElement对象转换为mshtml.IHTMLElementRender(尽管在C ++代码中)。

Unable to cast COM object of type 'mshtml.HTMLImgClass' to interface type 'mshtml.IHTMLElementRender'.
This operation failed because the QueryInterface call on the COM component for the interface with IID '{3050F669-98B5-11CF-BB82-00AA00BDCE0B}' failed due to the following error:
No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

当然,目标是获得完整的图像,因此也欢迎其他方法。以下是导致上述异常的代码。

public static void Main (string [] args)
{
    mshtml.HTMLDocument document = null;
    SHDocVw.InternetExplorer explorer = null;
    System.IntPtr hdc = System.IntPtr.Zero;
    mshtml.IHTMLElementRender render = null;
    mshtml._RemotableHandle handle = default(mshtml._RemotableHandle);

    try
    {
        explorer = new SHDocVw.InternetExplorer();
        explorer.Visible = true;

        try
        {
            explorer.Navigate("http://www.google.com/ncr");

            while (explorer.Busy)
            {
                // Striped events for SO example.
                System.Threading.Thread.Sleep(100);
            }

            document = (mshtml.HTMLDocument) explorer.Document;

            foreach (mshtml.IHTMLImgElement image in document.images)
            {
                Console.WriteLine();

                if ((image.width > 0) && (image.height > 0))
                {
                    // The following [if] will return false if uncommented.
                    //if (image.GetType().GetInterfaces().ToList().Contains(typeof(mshtml.IHTMLElementRender)))
                    {
                        using (Bitmap bitmap = new Bitmap(image.width, image.height))
                        {
                            using (Graphics graphics = Graphics.FromImage(bitmap))
                            {
                                hdc = graphics.GetHdc();
                                handle.fContext = hdc.ToInt32();
                                render = (mshtml.IHTMLElementRender) image; // Causes the exception.
                                //handle = (mshtml._RemotableHandle) Marshal.PtrToStructure(hdc, typeof(mshtml._RemotableHandle));
                                render.DrawToDC(ref handle);
                                graphics.ReleaseHdc(hdc);

                                // Process image here.

                                Console.Write("Press any key to continue...");
                                Console.ReadKey();
                            }
                        }
                    }
                }
            }
        }
        catch (System.Exception e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine("Stack Trace: " + e.StackTrace);
        }

        explorer.Quit();
    }
    catch (System.Exception e)
    {
        Console.WriteLine(e.Message);
        Console.WriteLine("Stack Trace: " + e.StackTrace);
    }
    finally
    {
    }

#if (DEBUG)
        Console.WriteLine();
        Console.Write("Press any key to continue...");
        Console.ReadKey();
#endif
}

我无法获得的一些链接:

1 个答案:

答案 0 :(得分:2)

您可以使用Regedit.exe轻松查看问题的根源。为了在进程边界之间桥接大峡谷的接口,它需要实现代理的代码和接口的存根。知道如何将接口方法参数序列化为可以从一个进程传输到另一个进程的RPC数据包的代码。

COM通过查看注册表来发现该代码。您也可以使用Regedit.exe,导航到HKCR \ Interfaces并向下​​滚动以匹配guid。你会看到{gu>很多的{guids},看起来像{305xxxx-98B5-11CF-BB82-00AA00BDCE0B}。是的,微软欺骗他们的guid,更容易调试,IE有很多。它们指向标准编组器并包含描述接口的类型库guid。

但你找到{3050F669-98B5-11CF-BB82-00AA00BDCE0B}。这基本上是异常消息告诉你的,它无法找到一种方法来编组接口指针。神秘的E_NOINTERFACE错误代码是后备方法无效的结果,无法查询IMarshal。

这是他们之间的一个折腾,他们忘了"并且"他们无法使其工作"。这个很大程度上倾向于太难以使它工作"。序列化渲染界面太困难了,对视频硬件的依赖性太大,当然在一台机器和另一台机器之间永远不会匹配。或者甚至在一台机器上,在进行任何方法调用之前需要正确初始化图形管道是非常棘手的。

那个降压停止的地方,你无法做到这一点。您需要自己渲染该图像,这并不容易。对不起,请不要拍摄信使。