Hebikuzure's Tech Memo

2012年1月22日

既定の整合性レベルとオートメーション

Filed under: Internet Explorer — hebikuzure @ 1:21 PM

Default Integrity Level and Automation
http://blogs.msdn.com/b/ieinternals/archive/2011/08/03/internet-explorer-automation-protected-mode-lcie-default-integrity-level-medium.aspx

一般のユーザーには馴染のないシナリオかもしれませんが、企業内アプリケーションなどでは、独自アプリケーションから Internet Explorer をオートメーションする事が良く行われます。こうした場合、Windows Vista + IE8 以上の環境では、Internet Explorer の保護モードと Loosely-Coupled IE の影響で、保護モード有効のセキュリティ ゾーン (例えばインターネット ゾーン) と保護モード無効のゾーン (例えばイントラネット ゾーン) を越えてページ遷移する場合、オートメーションの呼び出し側アプリケーションが、Internet Explorer への参照を失って制御できなくなる現象が起きます。これについて EricLaw’s IEInternals の解説記事を私訳しました。 (今回はコメントにも重要な情報が書かれているので、コメント部分まで訳しています)

Internet Explorer をオートメーションするような企業内アプリでは、ターゲットとなる Internet Explorer のバージョンが固定されている場合がまだ 一般的で、その多くは (特に日本国内では) IE6 を対象としているのではないかと思われますが、今後 Windows XP・IE6 のサポート切れに伴い新しいバージョンをターゲットに改修されるケースが増えてくると考えられます。そうした場合に IE6 ではなかったこうした挙動について理解し、記事に書かれているような適切な対処をする事が必要になります。

以下の文章は EricLaw’s IEInternals の 2011/8/3 の記事 Default Integrity Level and Automation を hebikuzure が私的に試訳したものです。翻訳については Microsoft Corporation および日本マイクロソフト株式会社とは無関係に hebikuzure が公開情報に基づき独自に行ったものであり、この文書の内容についての文責は公開者である hebikuzure にあります。翻訳の内容および技術的内容については正確を期すよう十分な注意を払っておりますが、誤りや不正確な部分が含まれている可能性がありますので、本文書を利用される際には原文も併せてご確認ください。


既定の整合性レベルとオートメーション

EricLaw [MSFT]

2011年8月3日 9時42分

StackOverflow で、danimajo さんが興味深いシナリオについて助力を求める質問をされています。基本的には、彼は Internet Explorer をオートメーションを通じて操作しようと試みているのですが、イントラネットのサイトに遷移すると非表示のブラウザーのインスタンスがあらわれ、それを制御する事ができなくなるのです。いったい何が起きているのでしょう?

保護モードの背景にあるもの

Internet Explorer の保護モードは、Windows の整合性レベル システムに基づくセキュリティー サンドボックスです。一つのプロセスは一つだけの整合性レベル (IL) を持ちますから、IE のインスタンスがインターネット (保護モード、LowIL) とイントラネット (非保護モード、MediumIL) の間を遷移すると、Internet Explorer は遷移を新しいプロセスでハンドルする必要があります。Vista 上の IE7 では、この動作はよく見える形であらわれます—新しいブラウザー ウィンドウが自動的に開かれます。IE8 では、Loosely-Coupled IE (LCIE) の導入により、この動作はより微妙に取り扱われます。

Loosely-Coupled IE の背景にあるもの

LCIE では、常に少なくとも二つのプロセスが存在します—ブラウザーのフレーム マネージャー プロセス (IE を管理者として実行しない限り、常に MediumIL で動作します) とブラウザーのタブ コンテンツ プロセスで、後者は以下のように実行されます:

  • 保護モードのサイトでは LowIL
  • イントラネット/信頼済みサイトでは MediumIL
  • HighIL (IE が管理者として実行された場合)

フレーム マネージャー プロセスはどの整合性レベルのタブも “可視的に” ホストできますから、ユーザーが LowIL のゾーンから MediumIL のゾーンのページに遷移すると、フレーム マネージャー プロセスは現在のタブ プロセスを異なる整合性レベルで動作するタブ プロセスに、サイレントに置き換えます。この動作は “Virtual Tab switch” (仮想タブ切り替え) と呼ばれます。

制御を失う場合

多くのシナリオへの互換性のため、Internet Explorer は既定のタブ プロセスを整合性低のタブであるとみなしています。したがって Internet Explorer が COM オートメーションにより生成される際、タブ プロセスの既定は整合性低のタブになります。ブラウザーはページ遷移により整合性中のタブ コンテンツ プロセスが必要であると判断すると、仮想タブ切り替えが実行されます。ここに興味深い点があります—なぜなら Internet Explorer をオートメーション経由で制御しているスクリプトやコードがその際に使用されなくなるタブ プロセスへの参照を持っていると、制御を失うのです。

制御を再獲得する

さて、呼び出し側がこの状況をハンドルする事は可能で、NewProcess イベント をトラップして適切に対処すればよいのです。とは言え、これにはそれなりの量のコードが必要ですし、場合によっては (一例として、イントラネットのページにのみ遷移するように構成されている場合など) 望ましい物ではなく、オートメーションの呼び出し側アプリケーションが単に自身の必要に応じて権限昇格をしてはじめから MediumIL で動作する Internet Explorer のインスタンスを呼び出す方が良いかもしれません。C++ や C# のような言語ではこれは容易で、CLSID_InternetExplorerMedium ("{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}") のインスタンスを CoCreate するだけです。この CLSID を利用すれば、オブジェクトは既定で MediumIL タブ コンテンツのプロセスになります。この動作の仕組みはとても単純です: レジストリ キー HKEY_CLASSES_ROOT\CLSID\{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}\LocalServer32 には "%ProgramFiles(x86)%\Internet Explorer\iexplore.exe" –startmediumtab という REG_EXPAND_SZ 値が含まれています。

残念ながら、私が説明できる限りでは、VBScript や JavaScript ような CScript や WScript の下で動作しているスクリプト言語は、CLSDI を CreateObject に渡す方法はありません—これは ProgID のみ受け付けます。更新情報: WndSks さんが以下のコメントで示しているように、以下の構文が利用できます Set IE = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")

CLSID_InternetExplorerMedium にマップされている ProgID はありませんが、単にレジストリを更新する事で簡単に作成できます。

Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\InternetExplorer.ApplicationMedium]
[HKEY_CLASSES_ROOT\InternetExplorer.ApplicationMedium\CLSID]
@="{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}"

こうすれば、MediumIL インスタンスの IE をスクリプトから呼び出せるようになります:

Set IE = CreateObject("InternetExplorer.ApplicationMedium")
‘ IE.Visible = false ‘ This is the default
IE.Navigate2 “http://intranetpage/”

保護モード外で実行されるページのみこのインスタンスで遷移するようにすれば、皆さんのオートメーション コードは参照を失うことなく、Internet Explorer のウィンドウも特に visible プロパティーを変更しない限り可視状態のままになります。

-Eric


コメント

RichB
2011年8月3日 午前11時33分
GetObject() を clsid: モニカに渡せばうまくいくのでは?
msdn.microsoft.com/…/aa392394(v=vs.85).aspx

EricLaw [MSFT]
2011年8月3日 午前11時38分
@RichB: うまくいかないなあ。もっとも僕はスクリプティングのエキスパートとは程遠いから。

WndSks
2011年8月3日 午後2時39分
Set IE = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
IE.Visible = true

EricLaw [MSFT]
2011年8月3日 午後2時43分
ありがとう、@WndSks—あなたの構文は Win7 でちゃんと動きました。

danimajo
2011年8月3日 午後9時31分
Eric さんありがとう! この答えはすばらしく役に立ちました!

コメントする »

まだコメントはありません。

RSS feed for comments on this post. TrackBack URI

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

WordPress.com で無料サイトやブログを作成.

%d人のブロガーが「いいね」をつけました。