none
Webbrowserコントロールの互換表示に関して(IEの互換表示ボタンと同等の操作) RRS feed

  • 質問

  • こんにちわ

    私はC#でWebbrowserコントロールを使用し、ブラウザアプリケーションの作成を行っています。

    Webbrowserコントロールを使用した場合、デフォルトだとIE7として動作し、HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATIONに値を設定することで、値に対応したIEバージョンで動作することは確認できました。しかし、この設定はアプリケーション起動時のみに反映されるよう見えます。

    特定サイトにアクセスする場合のみIE7にモードに切り替えたい為、アプリケーション動作中に、IE7⇔IE10を切り替える方法はありますでしょうか?


    • 編集済み MT2192 2013年11月22日 2:48
    2013年11月22日 2:46

回答

  • API HOOKを利用し、

    InternetConnectで対象のURLの場合、InternetHandleを保管し、HttpOpenRequestで保管したInternetHandleの場合、

    戻り値のRequestHandleを保管し、HttpSendRequestで保管したRequestHandleであった場合、RequestヘッダのUserAgentを書き換えて送信したところ、IE7とIE10を切り替えることができました。

    また、X-UA-Compatibleも設定したかった為、HttpSendRequestで保管したRequestHandleであった場合、HttpQueryInfoでX-UA-Compatibleが指定されている場合に、ResponseヘッダにX-UA-Compatibleが指定されてない場合のみ、IE=7を設定するようにしました。

    保管したHandleはInternetCloseHandleで削除しました。

    この方式でやりたかった事を実装することはできましたが、もっとスマートな方法があれば教えて頂きたいです。


    • 編集済み MT2192 2013年11月26日 2:10
    • 回答としてマーク MT2192 2013年12月11日 0:00
    2013年11月26日 2:09

すべての返信


  • また、次のレジストリ キーを使用すると、X-UA-Compatible ヘッダーが含まれていないページの Internet Explorer での処理方法を制御できます。

    なのだから、X-UA-Compatible metaタグで制御すれば?

    2013年11月22日 11:24
  • Browser Emulationの説明を読んだうえで、値を指定しているのでしょうか? …その前にブラウザーモードとドキュメントモードの関係は把握されているのでしょうか?

    たぶん、調べれば「互換表示ボタン」のような機能は実現できるとは思います。ただそれとは別に、近頃リリースされたIE11では「互換表示ボタン」自体が廃止されていて、ブラウザーウィンドウ上ではドキュメントモードを指定することはできなくなりました。IE10が動作するOSでは基本的にIE11も動作するため、この仕様変更について考慮する必要があると思います。

    # やり方そのものは調べていません。WebBrowser.WebBrowserSiteとかを扱うことになるのかな…? それとも別の方法かな?

    2013年11月22日 13:01
  • ウィンドウズスクリプトプログラマさん

    ご回答ありがとうございます。

    WebbrowserコントロールのDocumentCompletedイベントでは、Webbrowser.Documentに対して、METAタグなどを追加しても、反映されませんでした。実際にはWebbrowser.DocumentからHEADを取得し、HEADのChildrenにMETAタグを追加しましたが、

    表示したページのソースを取得したところ、追加したMETAタグがありませんでした。

    X-UA-Compatible metaタグはどのタイミングで追加できるのでしょうか?

    APIHOOKで、InternetReadFileなどを監視し、無理やり流し込むとかやらないとできないでしょうか?



    • 編集済み MT2192 2013年11月25日 1:12
    2013年11月25日 0:30
  • 佐祐理さん

    ご回答ありがとうございます。

    >その前にブラウザーモードとドキュメントモードの関係は把握されているのでしょうか?

    ブラウザウザモードはブラウザ自体の挙動を設定するモードと捉えています。なので、ブラウザモードをIE7にすれば、ドキュメントモードもIE7になると考えています。

    ドキュメントモードはWEBページの解釈のモードと考えているので、CSSなどの挙動がこの値に従うと捉えています。なのでIE10でドキュメントモードをIE7変更した場合は、navigator.userAgentはIE10、documet.documentModeはIE7を返すと考えています。

    >調べれば「互換表示ボタン」のような機能は実現できるとは思います。

    Webbrowserコントロールと互換表示で調べても、HITするのはレジストリによる変更しか見つからず、動的に互換表示を切り替える方法を探すことができませんでした。

    >WebBrowser.WebBrowserSiteとかを扱うことになるのかな…?

    WebBrowserSiteはIDocHostUIHandlerの実装にバグがあるようなので、実際にはIDocHostUIHandler等を継承したWebBrowserクラスを利用しています。その中でIHttpNegotiateを継承し、BeginningTransactionとOnResponseでリクエストヘッダのユーザエージェント及び、レスポンスヘッダにX-UA-Compatibleを追加してみましたが、引数がrefじゃない為、変更できませんでした。

    IE11への対応もありますが、まずはIE10環境での実装方法を探っています。


    • 編集済み MT2192 2013年11月25日 1:13
    2013年11月25日 0:52
  • API HOOKを利用し、

    InternetConnectで対象のURLの場合、InternetHandleを保管し、HttpOpenRequestで保管したInternetHandleの場合、

    戻り値のRequestHandleを保管し、HttpSendRequestで保管したRequestHandleであった場合、RequestヘッダのUserAgentを書き換えて送信したところ、IE7とIE10を切り替えることができました。

    また、X-UA-Compatibleも設定したかった為、HttpSendRequestで保管したRequestHandleであった場合、HttpQueryInfoでX-UA-Compatibleが指定されている場合に、ResponseヘッダにX-UA-Compatibleが指定されてない場合のみ、IE=7を設定するようにしました。

    保管したHandleはInternetCloseHandleで削除しました。

    この方式でやりたかった事を実装することはできましたが、もっとスマートな方法があれば教えて頂きたいです。


    • 編集済み MT2192 2013年11月26日 2:10
    • 回答としてマーク MT2192 2013年12月11日 0:00
    2013年11月26日 2:09
  • 汎用的な対処方法としてはローカル プロキシを作ってそこでヘッダーをごにょごににょすれば良いのではないかと。

    システム プロキシを変更せず、特定のアプリだけそのローカル プロキシを向くようにすれば、他への影響も最小限になるでしょう。


    hebikuzure

    2013年11月26日 10:29
    モデレータ
  • Hebikuzureさん

    ご回答ありがとうございます。

    確かにローカルプロキシを経由する方式をとれば対応できるかと思います。

    ただ、IEの開発者ツールからブラウザモードやドキュメントモードを変更できるので、Webbrowserコントロールからも何かしらの方法で

    これらの値を変更できるかなと思い質問させて頂きました。

    2013年11月27日 1:35
  • そもそもWebBrowserコントロールはデフォルトではIE7でしたっけ互換モードなわけで、それをコントロールする仕組みとしてFEATURE_BROWSER_EMULATIONが用意されている以上、動的に制御はできなさそうですね。

    一応、IDocHostUIHandlerやOLECMDIDなどには互換表示を制御する機能はなさそうでした。

    # 余談ですが、FEATURE_BROWSER_EMULATIONの指定方法にも不満があって、なんでedge指定できないのかと。8000にするとIE8になってしまうし、IE8に対して9000を指定した時の動作はundocumentedだし…IEのバージョンを調べてから書き込む値を決めるしかないのかなぁ…。

    2013年11月27日 4:05
  • 佐祐理さん

    ご回答ありがとうございます。

    >IDocHostUIHandlerやOLECMDIDなどには互換表示を制御する機能はなさそうでした。

    調べて頂きありがとうございます。IDocHostUIHandlerやIOleClientSite、IOleCommandTargetは継承して使用してますが、これられでは互換性の操作はできないようですね。

    >IEのバージョンを調べてから書き込む値を決めるしかないのかなぁ…。

    確かにedge指定できると便利ですね。現状はレジストリからIEのバージョンを取得してそれに対応したFEATURE_BROWSER_EMULATIONの値を起動時に書き込むようにしています。

    IEコンポーネントを利用しているブラウザを探したところAnciaやSleipnir4など互換表示を動的に操作できるものがあったので、何かしらの方法はあると思うんですけどね・・・。

    Sleipnirは強制的にX-UA-Compatibleタグを入れているように見えますが、Anciaはわかりませんでした。


    2013年11月27日 6:45
  • API HOOKの方式で今のところ問題なく動作していますが、HTTPSのCONNECTリクエスト時は、HttpSendRequestがコールされない為、UserAgentの変更ができませんでした。

    ただ、CONNECT時は特に問題ないかなと考えています。ちょっと気持ち悪いですが・・・。

    引き続き、回答をお待ちしていますが、もう少し自分でも調査をし、有効な方法が見つからなければ解決とさせて頂きます。

    2013年12月4日 2:52