1

新しいものを起動して既存の IE 10 インスタンスに接続する C# .NET 4 WinForms アプリ (MSHTML 7 を使用) があります。すべての画像を繰り返し処理し、それらをダウンロードして操作します。イメージはすでに 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 に一致させることもできます。{305xxxx-98B5-11CF-BB82-00AA00BDCE0B} のような多くの {guid} が表示されますはい、Microsoft は GUID をだましており、デバッグが容易です。IE にはかなり多くの GUID があります。これらは標準マーシャラーを指し、インターフェイスを記述するタイプ ライブラリ GUID を含みます。

しかし、{3050F669-98B5-11CF-BB82-00AA00BDCE0B} は見つかりません。これは基本的に例外メッセージが伝えていることであり、インターフェイス ポインターをマーシャリングする方法が見つかりません。ミステリアスな E_NOINTERFACE エラー コードは、フォールバック アプローチが機能せず、IMarshal のクエリに失敗した結果です。

これは、「彼らは忘れていた」と「彼らはそれを機能させることができなかった」の間のちょっとしたトスアップです. これは、「機能させるのが難しすぎる」ことに大きく傾いています。レンダー インターフェースのシリアル化は非常に難しく、ビデオ ハードウェアへの依存関係が多すぎて、マシン間で一致することはありません。または、1 台のマシンでさえ、メソッド呼び出しを行う前にグラフィックス パイプラインを適切に初期化する必要があるのは、非常に注意が必要です。

それはお金が止まるところです、あなたはこれを機能させることはできません. その画像を自分でレンダリングする必要がありますが、簡単ではありません。申し訳ありませんが、メッセンジャーを撃たないでください。

于 2013-06-04T13:37:19.423 に答える