2013年10月4日金曜日

【解決】PowerShellでInternetExplorerを操作するときにエラーが発生

メイン開発機で作っていたスクリプトをほとんど素のWindows7機にもっていって動作確認した時のこと。

InternetExplorerを操作する箇所で下記エラーが発生

"getElementById" のオーバーロードで、引数の数が "1" であるものが見つかりません。

該当コード部分は
$doc = $ie.document
$username_el = $doc.getElementByID("username")

まったくもって意味不明
オブジェクトがないということか?
とも思ったけど document自体はCOMコンポーネントのオブジェクトとして認識されている。

いろいろ、調査。
で、下記可能性が見つかった

1.InetrnetExplorerのセキュリティ設定が悪いんじゃないか。
   セキュリティの保護モードをオフにしろ、という記述(海外のサイト)
  →これはほぼ嘘だと思う。自分のメイン機では”オン”で動いている。
   サイトによってエラーが出たり出なかったり、という時は疑ってもよいのかもしれないが。

2.IEのバージョンによりアクセス方法が違う
  IE9だとエラーが出るので、下記ページのようにしろ、とある。
  おいらのはIE10なんですけど、と思いながら試してみる。

  http://cezne.tumblr.com/post/23228713564/ie9-powershell

  これでも動くことは動く。
  これが大変くせもの。これで確かにいけるのだけれどページ遷移すると”忘れる”
  ので最初のアクセスしか有効でない。実質”使えない”
  かつ使うすべてのメソッドをこれでアクセスするなんて考えただけで寒気が…

 
 

ここでなんとなく思う。
オブジェクトはそこにいる。
決して情報を取れていないということではなくアクセス方法がわからないだけ

頭の中になぜか”アセンブリ”という言葉は浮かぶ。

アセンブリの一覧はこのページのようにして取れる。

 [Appdomain]::CurrentDomain.GetAssemblies() | %{$_.GetName().Name}

これでメイン機と動いていないマシンで差をとった。

メイン機にあって、動いていないマシンにないエントリが見つかった

Microsoft.mshtml

うーん、それっぽい。

(あとの追調査でわかったことだが、navigateで有効なサイトにアクセスして documentプロパティに
アクセスしたときに初めて読み込まれるようだ。)

なんか来た。

あとはmshtmlを探せばよいっぽい。
が、探すファイルはMicrosoft.mshtml.dllであって、mshtml.dllではないようだ。
確かに動かないマシンにはないようだ。

メイン機には開発ツールをてんこ盛りにしているのでどれをインストールした時に入ったのかとかさっぱり。
ファイルを一つ持っていけばよかったのかもしれないがなんとなく”ちゃんと”インストールしてみることにする。
(依存関係とかがあってあとで悩むのもいやだし)

ネットの情報ではMicrosoft .NET Framework 2.0 SDK に入っているらしい。
あと、Global Assemblyっていうやつに読み込まないといけないらしいとの情報も。

でSDKを入れた。
インストール後、検索するとやつは、

C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll

に居た。

ここでPowerShellを立ち上げてテストしてみたけどだめ。

で、直接読み込んでみた。

[System.Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll")

なんかメッセージが出て読み込めた。

上記チェックをやった。 やったー動いた!
これをやればなんとかなる!

後日談

 動くようになったマシンを再起動したら上記で読み込まなくてもdocumentプロパティをアクセスした時点で自動的に読み込まれるようになった。(ログオフでもよかったのかもしれないが分からない)

GACというところ(c:\windows\assembly)に登録されるとマシン全体で使えるようだ。
ここには上記.net SDKのインストーラが登録してくれるみたい。
(ここはフォルダに見えているけどメタファーとしてそうなっているだけで実質は違うらしい)

もしGACにあるアセンブリを読み込むには
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.mshtml")
でよいらしい。

かなりネットをさまよったがなんとか一日で解決できた。
しかしみんなどうやって解決してるんだ?

0 件のコメント:

コメントを投稿