1

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

我通过的一些链接无济于事:

4

1 回答 1

2

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

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

但是您不会找到 {3050F669-98B5-11CF-BB82-00AA00BDCE0B}。这基本上就是异常消息告诉您的内容,它找不到编组接口指针的方法。神秘的 E_NOINTERFACE 错误代码是回退方法也不起作用的结果,无法查询 IMarshal。

这是“他们忘记了”和“他们无法让它工作”之间的一个折腾。这个严重倾向于“太难使其工作”。序列化渲染接口太难了,对视频硬件的依赖太多,当然这在一台机器和另一台机器之间永远不会匹配。甚至在一台机器上,在进行任何方法调用之前正确初始化图形管道的需求太棘手了。

这就是降压停止的地方,你无法完成这项工作。您需要自己渲染该图像,这并不容易。对不起,请不要向信使开枪。

于 2013-06-04T13:37:19.423 回答