IE9をType.InvokeMemberで操作
IE9では、Type.InvokeMemberを利用して、IEを操作することになるのだけど、情報が少ない。
従って、実験を繰り返して調べることになる。
ここでは、その研究結果のコードを掲載しておきます。もっと洗練された方法があるはずだけれど、とりあえず動くものを作るのが必要なので、野暮ったいのは勘弁して下さい。
IE8までは、もっと簡単なコードで充分だったのに、IE9では厳密に指定しないと駄目。
Visual Studio 2010 / VB.net用
http://www.moderns.co.jp/files/UsingIE9Object.zip
Imports System.Reflection Public Class Form1 Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 'BindingFlags.GetProperty などを短く置き変えることが出来る。 'Dim getPr As BindingFlags = BindingFlags.GetProperty 'Dim setPr As BindingFlags = BindingFlags.SetProperty 'Dim invMe As BindingFlags = BindingFlags.InvokeMethod Dim ieObj As Object ieObj = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る If ieObj Is Nothing Then MsgBox("IE Nothing") End If ieObj.Visible = True '見えるようにする Dim uri As String = My.Computer.FileSystem.CombinePath(My.Application.Info.DirectoryPath, "IE9.html") 'uri = "http://www.moderns.co.jp/" Try ieObj.Navigate2(uri) Catch MsgBox("file not found:" & vbCrLf & uri) Exit Sub End Try Call ieWait(ieObj) Dim ieDoc As Object Dim typ As Type typ = Type.GetTypeFromProgID("mhtmlfile") 'あるいは、こちらでもOK。 'typ = Type.GetTypeFromCLSID(New System.Guid("{3050F4E7-98B5-11CF-BB82-00AA00BDCE0B}")) 'ieDoc = ieObj.Document 'IE8までは、こうした文法で良かった。IE9では、以下のようにするのが良い。 ieDoc = typ.InvokeMember("document", BindingFlags.GetProperty, Nothing, ieObj, Nothing) 'Title TextBox1.Text &= "title: " & typ.InvokeMember("title", BindingFlags.GetProperty, Nothing, ieDoc, Nothing) & vbCrLf 'URLは大文字 TextBox1.Text &= "URL: " & typ.InvokeMember("URL", BindingFlags.GetProperty, Nothing, ieDoc, Nothing) & vbCrLf 'Linkの数 TextBox1.Text &= "Link count : " & typ.InvokeMember("links", BindingFlags.GetProperty, Nothing, ieDoc, Nothing).length & vbCrLf 'TextBox1.Text &= "URL: " & GetP("URL", ieDoc) & vbCrLf 'TextBox1.Text &= "Link count : " & GetP("links", ieDoc).length & vbCrLf 'Typeを表示 mshtml.HTMLAnchorElementClass となる。 TextBox1.Text &= typ.InvokeMember("links", BindingFlags.GetProperty, Nothing, ieDoc, Nothing)(1).ToString & vbCrLf '2番目のリンクのInnerText TextBox1.Text &= "Second Link InnterText : " & typ.InvokeMember("innerText", BindingFlags.GetProperty, Nothing, typ.InvokeMember("links", BindingFlags.GetProperty, Nothing, ieDoc, Nothing)(1), Nothing) & vbCrLf '2番目のリンクをクリックする。 'Dim links As Object = typ.InvokeMember("links", BindingFlags.GetProperty, Nothing, ieDoc, Nothing) 'link 全部のObject 'typ.InvokeMember("click", BindingFlags.InvokeMethod, Nothing, links(1), Nothing) 'links(1)は、2番目のlinkを意味する。 'あるいは、こちらでも同じ。 'Dim link2 As Object = typ.InvokeMember("links", BindingFlags.GetProperty, Nothing, ieDoc, Nothing)(1) '2番目のlinkのObject (0)1番目 (1)2番目 (2)3番目 ・・・ 'typ.InvokeMember("click", BindingFlags.InvokeMethod, Nothing, link2, Nothing) 'Call ieWait(ieObj) TextBox1.Text &= vbCrLf 'Body Elementを確定する2種類の方法 '1 how to get the body object Dim htmlBody As Object htmlBody = typ.InvokeMember("body", BindingFlags.GetProperty, Nothing, ieDoc, Nothing) 'htmlBody = GetP("body", ieDoc) TextBox1.Text &= "body innerHTML : " & typ.InvokeMember("innerHTML", BindingFlags.GetProperty, Nothing, htmlBody, Nothing) & vbCrLf & vbCrLf '2 how to get the body object Dim htmlBody2 As Object htmlBody2 = typ.InvokeMember("getElementsByTagName", BindingFlags.InvokeMethod, Nothing, ieDoc, {"body"})(0) 'htmlBody2 = InvokeM("getElementsByTagName", ieDoc, {"body"})(0) TextBox1.Text &= "body innerHTML : " & typ.InvokeMember("innerHTML", BindingFlags.GetProperty, Nothing, htmlBody2, Nothing) & vbCrLf & vbCrLf 'Form Element Dim formElm As Object = typ.InvokeMember("getElementsByName", BindingFlags.InvokeMethod, Nothing, ieDoc, {"formName1"}) Dim inputElm As Object = typ.InvokeMember("getElementsByTagName", BindingFlags.InvokeMethod, Nothing, formElm(0), {"input"}) 'InputBox inputElmを利用 For i As Integer = 0 To inputElm.length - 1 TextBox1.Text &= typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) & vbCrLf If typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) = "siteurl" Then typ.InvokeMember("value", BindingFlags.SetProperty, Nothing, inputElm(i), {"input value"}) End If Next 'CheckBox inputElmを利用 For i As Integer = 0 To inputElm.length - 1 TextBox1.Text &= typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) & vbCrLf If typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) = "c1" Then typ.InvokeMember("checked", BindingFlags.SetProperty, Nothing, inputElm(i), {"True"}) End If Next 'RadioButton inputElmを利用 For i As Integer = 0 To inputElm.length - 1 TextBox1.Text &= typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) & vbCrLf If typ.InvokeMember("name", BindingFlags.GetProperty, Nothing, inputElm(i), Nothing) = "r1" Then typ.InvokeMember("checked", BindingFlags.SetProperty, Nothing, inputElm(i), {"True"}) End If Next 'Select and Option Dim selectElm As Object = typ.InvokeMember("getElementsByName", BindingFlags.InvokeMethod, Nothing, ieDoc, {"sele1"})(0) Dim optionsElm As Object = typ.InvokeMember("getElementsByTagName", BindingFlags.InvokeMethod, Nothing, selectElm, {"option"}) For i As Integer = 0 To optionsElm.length - 1 TextBox1.Text &= typ.InvokeMember("innerText", BindingFlags.GetProperty, Nothing, optionsElm(i), Nothing) & vbCrLf If typ.InvokeMember("innerText", BindingFlags.GetProperty, Nothing, optionsElm(i), Nothing) = "def" Then typ.InvokeMember("selected", BindingFlags.SetProperty, Nothing, optionsElm(i), {"True"}) End If Next 'TextArea Dim textAElem As Object textAElem = typ.InvokeMember("getElementsByName", BindingFlags.InvokeMethod, Nothing, ieDoc, {"te1"}) 'textAElem = InvokeM("getElementsByName", ieDoc, {"te1"}) typ.InvokeMember("value", BindingFlags.SetProperty, Nothing, textAElem(0), {"textarea value"}) 'Call SetP("value", textAElem(0), {"textarea value"}) 'Form InnerHTML TextBox1.Text &= vbCrLf & "Form innerHTML : " & GetP("innerHTML", InvokeM("getElementsByName", ieDoc, {"formName1"})(0)) & vbCrLf End Sub ''' <summary> ''' IEの表示が完了するまで待つ ''' </summary> ''' <param name="ieObj"></param> ''' <remarks></remarks> Sub ieWait(ByRef ieObj As Object) Try Dim sw As New Stopwatch sw.Start() Do While (ieObj.Busy OrElse ieObj.ReadyState <> SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) _ AndAlso sw.Elapsed <= New TimeSpan(0, 0, 0, 20) '読み込み中でも、CheckWatingSecond(20秒)を超えたら抜ける Application.DoEvents() '読み込み中なら待つ Loop sw = Stopwatch.StartNew() Do While sw.Elapsed <= New TimeSpan(0, 0, 0, 0, 1000) '念のため読み込みが終わってもさらに1秒待つ Application.DoEvents() Loop sw.Reset() Catch ex As Exception 'IEが閉じられていた場合などエラーになるので、それをキャッチする。 MsgBox("Error") End Try End Sub ''' <summary> ''' InvokeMemberの、GetPropertyを実行 ''' </summary> ''' <param name="name1"></param> ''' <param name="target1"></param> ''' <param name="args1"></param> ''' <returns></returns> ''' <remarks></remarks> Function GetP(ByVal name1 As String, ByVal target1 As Object, Optional ByVal args1 As Object = Nothing) Dim typ As Type = Type.GetTypeFromProgID("mhtmlfile") Return typ.InvokeMember(name1, BindingFlags.GetProperty, Nothing, target1, args1) End Function ''' <summary> ''' InvokeMemberの、SetPropertyを実行 ''' </summary> ''' <param name="name1"></param> ''' <param name="target1"></param> ''' <param name="args1"></param> ''' <returns></returns> ''' <remarks></remarks> Function SetP(ByVal name1 As String, ByVal target1 As Object, Optional ByVal args1 As Object = Nothing) Dim typ As Type = Type.GetTypeFromProgID("mhtmlfile") Return typ.InvokeMember(name1, BindingFlags.SetProperty, Nothing, target1, args1) End Function ''' <summary> ''' InvokeMemberの、InvokeMethodを実行 ''' </summary> ''' <param name="name1"></param> ''' <param name="target1"></param> ''' <param name="args1"></param> ''' <returns></returns> ''' <remarks></remarks> Function InvokeM(ByVal name1 As String, ByVal target1 As Object, Optional ByVal args1 As Object = Nothing) Dim typ As Type = Type.GetTypeFromProgID("mhtmlfile") Return typ.InvokeMember(name1, BindingFlags.InvokeMethod, Nothing, target1, args1) End Function End Class
対象のHTML IE9.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>IE9 Object</title> </head> <body> <p><a href="http://www.moderns.co.jp/">modern design laboratory</a></p> <p><a href="http://www.msignal.info/">M.Signal</a></p> <p><a href="http://www.linkget.info/">LinkGet</a></p> <form action="form1.html" name ="formName1" method="get"> <input type="text" name="siteurl" size="20" /> <input type="checkbox" name="c1" value=""> <input type="checkbox" name="c2" value=""> <input type="radio" name="r1" value="b1"> <input type="radio" name="r1" value="b2"> <input type="radio" name="r1" value="b3"> <select name="sele1" size="1" tabindex="0"> <option value="">abc</option> <option value="">def</option> <option value="">ghi</option> </select> <textarea name="te1" rows="2" cols="20" tabindex="0"></textarea> </form> </body> </html>