Windowsフォームには、Windowsアプリケーション内にWebページを表示するためのWebBrowserコントロールが用意されている。このWebBrowserコントロールでは、指定したページへの移動や、戻る、進むなどのブラウザと同様の操作に加え、コントロールで表示されているドキュメント内の要素をプログラムから操作することも可能だ。
本稿では、WebBrowserコントロールに表示されている入力フォーム内のテキストボックスにプログラムから値を入力し、さらにそのフォームをサブミット(フォームの内容を送信)する、あるいはフォームにあるボタンをクリックする方法を紹介する。この方法により、Webアプリケーションのテストや、Webアプリケーションへの自動ログインなどが可能になる。
Googleの検索ページを操作するサンプル・プログラム
ここでは最初に、本稿で作成するサンプル・プログラムの動作を説明する。これは3つのボタンと1つのWebBrowserコントロールを配置したWindowsアプリケーション(下図参照)で、これら3つのボタンでGoogleの検索ページを操作する。
具体的には、プログラム起動時にGoogleの検索ページが表示され、ここで[検索語の入力]ボタン(下図の(1))をクリックすると、ページに表示されているテキストボックスに「C#」という文字列が自動的に入力される。さらに、(2)あるいは(3)のボタンをクリックすると、検索が実行されて検索結果ページが表示される。
このようにプログラムからWebページを操作する場合、事前にそのHTMLのソースをチェックして、操作対象となるHTML要素を明確にしておく必要がある。Googleの検索ページのソースを見ると、フォームの定義部分で次のような記述を見つけることができる。
<form action="/search" name=f >
<input name=q size=55 value="" …… >
<input name=btnG type=submit value="Google 検索" …… >
……
この記述から、フォーム(<form>要素)には「f」という名前(name属性)が付けられており、またテキストボックス(<input>要素)には「q」、[Google検索]ボタン(サブミット・ボタン。「type=submit」という属性が付いている<input>要素)には「btnG」という名前が付けられていることが分かる。
以上が確認できれば、それぞれの名前で各HTML要素を検索し、それを外部から操作することが可能になる。
3つのボタンのイベント・ハンドラの内容
Webページの表示内容はHTML要素(HTMLタグ)の集まりであるが、WebBrowserコントロールのドキュメント上では、これらの要素はHtmlElementクラス(System.Windows.Forms名前空間)のオブジェクトで表される。また、HtmlElementオブジェクトのコレクションとして、HtmlElementCollectionクラス(System.Windows.Forms名前空間)が定義されている。
一方、WebBrowserコントロールのドキュメントは、HtmlDocumentクラス(System.Windows.Forms名前空間)のオブジェクトで表され、これはWebBrowserコントロールのDocumentプロパティから取得できる。そして、そのAllプロパティからは、ドキュメント内の全要素を含んだHtmlElementCollectionオブジェクトを取得できる。
以上を踏まえたうえで、上記サンプル・プログラムの3つの操作の内容を次に示す。なお、上記サンプル・プログラムでは、WebBrowserコントロールをフォームに配置する際に、そのUrlプロパティに「http://www.google.co.jp」をセットして、起動時にGoogleの検索ページが開くようにしている。
■テキストボックスに文字列をセット
特定のテキストボックスに文字列をセットするには、そのテキストボックスを表すHtmlElementオブジェクトを取得し、それに含まれるテキストをInnerTextプロパティにより設定することができる。
従って、上記サンプル・プログラムの[検索語の入力]ボタンのイベント・ハンドラは次のようになる。
private void button1_Click(object sender, EventArgs e)
{
HtmlElementCollection all = webBrowser1.Document.All;
HtmlElementCollection forms = all.GetElementsByName("q");
forms[0].InnerText = "c#"; // テキストボックスに「C#」を入力
}
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim all As HtmlElementCollection = WebBrowser1.Document.All
Dim forms As HtmlElementCollection = all.GetElementsByName("q")
forms(0).InnerText = "c#" ' テキストボックスに「C#」を入力
End Sub
GetElementsByNameメソッドは、コレクションであるHtmlElementCollectionオブジェクトから、特定の名前を持つ要素を取得するためのものだ。複数の要素が同じ名前を持つ可能性があるため、このメソッドの戻り値もHtmlElementCollectionオブジェクトとなる。
このコードでは、「q」という名前の要素は1つという前提で記述しているが、通常はプロパティにアクセスする前に、コレクションの要素数をチェックすべきだ。
■フォームのサブミット
フォームのサブミットでは、上記と同様に、まず要素名からフォームを表すHtmlElementオブジェクトを取得する。そして、「"submit"」という引数でInvokeMemberメソッドを呼び出せばよい。コードは次のようになる。
private void button2_Click(object sender, EventArgs e)
{
HtmlElementCollection all = webBrowser1.Document.All;
HtmlElementCollection forms = all.GetElementsByName("f");
forms[0].InvokeMember("submit"); // フォームのサブミット
}
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim all As HtmlElementCollection = WebBrowser1.Document.All
Dim forms As HtmlElementCollection = all.GetElementsByName("f")
forms(0).InvokeMember("submit") ' フォームのサブミット
End Sub
■ボタンのクリック
上記のようにフォームを直接サブミットする代わりに、サブミット・ボタンをクリックしてもフォームをサブミットできる。ボタンをクリックするには、そのボタンのHtmlElementオブジェクトを取得し、「"submit"」という引数でInvokeMemberメソッドを呼び出す。
private void button3_Click(object sender, EventArgs e)
{
HtmlElementCollection all = webBrowser1.Document.All;
HtmlElementCollection forms = all.GetElementsByName("btnG");
forms[0].InvokeMember("click"); // ボタンのクリック
}
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim all As HtmlElementCollection = WebBrowser1.Document.All
Dim forms As HtmlElementCollection = all.GetElementsByName("btnG")
forms(0).InvokeMember("click") ' ボタンのクリック
End Sub
■HTML要素のそのほかの探し方
今回はname属性の値が事前に分かっていたため、GetElementsByNameメソッドによりHTML要素のオブジェクトを特定した。name属性ではなく、id属性が付けられている場合には、id属性の内容でHTML要素を検索するGetElementByIdメソッドが使える。
HtmlElement usernameTextbox =
webBrowser1.Document.GetElementById("username");
Dim usernameTextbox As HtmlElement = _
webBrowser1.Document.GetElementById("username")
HTML要素にname属性やid属性が付けられていない場合には、GetElementsByTagNameメソッドを使って、HTML要素のタグ名から検索する方法が有効だ。
HtmlElementCollection buttons =
webBrowser1.Document.GetElementsByTagName("button");
Dim buttons As HtmlElementCollection = _
webBrowser1.Document.GetElementsByTagName("button")
この場合には、通常複数のHTML要素が見つかるため、HTML上での並び順や、属性の値(GetAttributeメソッドにより属性名からその値を取得可能)を手掛かりにして、HTML要素を絞り込む必要がある。
利用可能バージョン:.NET Framework 2.0以降
カテゴリ:Windowsフォーム 処理対象:WebBrowserコントロール
使用ライブラリ:WebBrowserコントロール(System.Windows.Forms名前空間)
使用ライブラリ:HtmlElementクラス(System.Windows.Forms名前空間)
使用ライブラリ:HtmlElementCollectionクラス(System.Windows.Forms名前空間)
Copyright© Digital Advantage Corp. All Rights Reserved.