WebView2コントロールでの操作
WebView2コントロールで行える操作や方法について解説します。
目次
WebView2の初期化
WebView2コントロールを使用するには、フォームにWebView2コントロールを貼り付けるだけではダメで、
初期化メソッドEnsureCoreWebView2Async
の実行が必要です。
await
で実行して初期化の完了を待ってください。
初期化完了を待たないでwebView2.CoreWebView2
にアクセスするとNullReferenceException
が発生します。
Private Async Function InitializeAsync() As Task Await WebView2.EnsureCoreWebView2Async(Nothing) End Function Private Async Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load Await InitializeAsync() WebView2.CoreWebView2.Navigate("https://web.biz-prog.net/") End Sub
private async Task InitializeAsync() { await webView2.EnsureCoreWebView2Async(null); } private async void Form1_Load(object sender, EventArgs e) { await InitializeAsync(); webView2.CoreWebView2.Navigate("https://web.biz-prog.net/"); }
上記のように初期化を待ちたくない場合は、初期化完了イベントの
CoreWebView2InitializationCompleted
が発生してから、
後続処理を行いましょう。Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load InitializeAsync() End Sub Private Sub InitializeAsync() '初期化完了時のイベント AddHandler WebView2.CoreWebView2InitializationCompleted, AddressOf webView2CoreWebView2InitializationCompleted Await WebView2.EnsureCoreWebView2Async(Nothing) End Sub Private Sub webView2_CoreWebView2InitializationCompleted(sender As Object, e As Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs) Handles webView2.CoreWebView2InitializationCompleted Debug.WriteLine("初期化完了") WebView2.CoreWebView2.Navigate("https://web.biz-prog.net/") End Sub
private void Form1_Load(object sender, EventArgs e) { InitializeAsync(); } private void InitializeAsync() { //初期化完了時のイベント webView2.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted; webView2.EnsureCoreWebView2Async(null); } private void WebView2_CoreWebView2InitializationCompleted(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e) { Debug.WriteLine("初期化完了"); webView2.CoreWebView2.Navigate("https://web.biz-prog.net/"); }
WebView2コントロールでWebサイトを表示する方法
WebView2コントロールを使ってWebページを表示するにはwebView2.CoreWebView2.Navigate
メソッドを使用します。
WebView2.CoreWebView2.Navigate("https://web.biz-prog.net/") '開きたいURL
webView2.CoreWebView2.Navigate("https://web.biz-prog.net/"); //開きたいURL
その他の操作方法については、 左メニューの「WebView2コントロール 基本操作」を参照してください。
WebView2のサイト表示待ち方法
navigateメソッドでWebページを表示したり、リンクのクリックを行ったり、Submitを行った場合などは、ページの読み込み・表示が終わるまでの待機する処理が必要です。
以下の処理によりページの表示が終わるまで待機します。
Imports Microsoft.Web.WebView2.Core Public Class Form1 Private ReadOnly condition As New System.Threading.CountdownEvent(1) Private Sub FormWebView2_Load(sender As Object, e As EventArgs) Handles MyBase.Load InitializeAsync() End Sub Async Sub InitializeAsync() Await WebView2.EnsureCoreWebView2Async(Nothing) End Sub Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim result As String = "" 'サイトの表示を開始 WebView2.CoreWebView2.Navigate("https://web.biz-prog.net/") '非同期実行 Await Task.Run( Sub() '読み込み完了まで待機 If condition.Wait(5000) Then result = "ok" Else result = "timeout" End If End Sub ) MsgBox(result) End Sub Private Sub WebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs) Handles WebView2.NavigationCompleted '読み込み結果を判定 If e.IsSuccess Then Console.WriteLine("complete") Else Console.WriteLine(e.WebErrorStatus) End If 'シグナル初期化 condition.Signal() System.Threading.Thread.Sleep(1) condition.Reset() End Sub End Class
using System; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Web.WebView2.Core; public partial class Form1 : Form { readonly CountdownEvent condition = new CountdownEvent(1); private void Form1_Load(object sender, EventArgs e) { InitializeAsync(); } async void InitializeAsync() { await webView2.EnsureCoreWebView2Async(null); webView2.CoreWebView2.NavigationCompleted += webView2_NavigationCompleted; } private async void button1_Click(object sender, EventArgs e) { string result = ""; //サイトの表示を開始 webView2.CoreWebView2.Navigate("https://web.biz-prog.net/"); //非同期実行 await Task.Run(() => { //読み込み完了まで待機 if (condition.Wait(5000)) result = "ok"; else result = "timeout"; }); MessageBox.Show(result); } private void webView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { //読み込み結果を判定 if (e.IsSuccess) Console.WriteLine("complete"); else Console.WriteLine(e.WebErrorStatus); //シグナル初期化 condition.Signal(); System.Threading.Thread.Sleep(1); condition.Reset(); } }
WebView2コントロールでDOM操作する方法
InternetExplorer操作やWebBrowserコントロールであれば直接DOM操作できるメソッド・プロパティ(getElementByIdメソッドやdocumentプロパティ等)がありましたが、
WebView2コントロールにはこのようなメソッドはありません。
WebView2コントロールでは、ExecuteScriptAsync
メソッドを使用して、JavaScriptのコードを実行してWebページを操作します。
ExecuteScriptAsync
メソッドの引数に、実行したいJavaScriptのコードの文字列を渡して実行します。
JavaScriptのコードで、DOM要素にテキストを設定したり、フォームをSubmitします。
また、DOM等の値を取得する場合は、JavaScriptで値を参照するコードを書けば、ExecuteScriptAsync
メソッドの戻り値として取得できます。
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'Yahooの検索欄に文字を設定する Await WebView2.ExecuteScriptAsync($"document.getElementsByName('p')[0].value = 'プログラムでネットサーフィン!';") '検索欄の文字列を取得する Dim result = Await WebView2.ExecuteScriptAsync("document.getElementsByName('p')[0].value") MessageBox.Show(result) 'submitして検索を実行 Await WebView2.ExecuteScriptAsync($"document.forms['sf1'].submit();") End Sub
async private void button1_Click(object sender, EventArgs e) { //Yahooの検索欄に文字を設定する await webView2.ExecuteScriptAsync($"document.getElementsByName('p')[0].value = 'プログラムでネットサーフィン!';"); //検索欄の文字列を取得する var result = await webView2.ExecuteScriptAsync("document.getElementsByName('p')[0].value"); MessageBox.Show(result); //submitして検索を実行 await webView2.ExecuteScriptAsync($"document.forms['sf1'].submit();"); }
上記、スクリプトを複数に分けて実行していますが、1つにまとめて実行することもできます。
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'Yahooの検索欄に文字を設定する。submitして検索を実行 Await WebView2.ExecuteScriptAsync($"document.getElementsByName('p')[0].value = 'プログラムでネットサーフィン!'; document.forms['sf1'].submit();") End Sub
async private void button1_Click(object sender, EventArgs e) { //Yahooの検索欄に文字を設定する。submitして検索を実行 await webView2.ExecuteScriptAsync($"document.getElementsByName('p')[0].value = 'プログラムでネットサーフィン!'; document.forms['sf1'].submit();"); }
関数を定義して長いコードを記述し、jsonで実行結果を取得するようにしてみました。
Dim js As String = "var LinkClick_MatchText = function (text) { for (let i = 0; i < document.links.length; i++) { if (document.links[i].innerText == text) { document.links[i].click(); return { ""result"": ""ok"" } } } return { ""result"" : ""notarget""} } LinkClick_MatchText('テキスト')" Dim jsonString As String = Await wb.ExecuteScriptAsync(js) Dim json = JsonSerializer.Deserialize(Of Dictionary(Of String, String))(jsonString) Console.WriteLine(json("result"))
var js = @"var LinkClick_MatchText = function (text) { for (let i = 0; i < document.links.length; i++) { if (document.links[i].innerText == text) { document.links[i].click(); return { ""result"": ""ok"" } } } return { ""result"" : ""notarget""} } LinkClick_MatchText('テキスト')"; var jsonString = await wb.ExecuteScriptAsync(js); var json = JsonSerializer.Deserialize<Dictionary<String, String>>(jsonString); Console.WriteLine(json["result"]);
実行するJavaScriptの中で、async/awaitの非同期で実行するコードを書いてみましたが、実行するとそこで処理が中断されました。
sleepさせようとループをいれても描画自体がとまってうまくいきません。
もしかしたら実行するJavaScriptは非同期処理には対応していないのかもしれません。
要素の指定や操作方法のサンプルについては、左メニューの「WebView2コントロール HTML要素の指定」 「WebView2コントロール HTML要素の操作(DOM操作)」を参照してください。
WebView2コントロールでJavaScriptを実行する方法
WebView2コントロールでは、JavaScriptのコードを好きな時に実行させる事ができます。
WebView2コントロール自身では直接WebページのDom操作やJavaScriptの制御を行う事ができませんので、
JavaScriptのコードを実行することで色々な操作を行います。
上記のしたWebView2コントロールでDOM操作する方法にて要素の操作を行ったり、
htmlの情報を収集して取得することができます。
以下、JavaScriptを使ってhtml情報を収集するサンプルです。
C#/VB側のコード
string title = await areaInfo.WebView.ExecuteScriptAsync("document.querySelector('h1').innerText");
注意
・JavaScriptの実行でエラー等で正しく動いていない場合は、VB/C#で取得した値がnull
になっています。
取得結果はまずnull
判定して、JavaScriptが正常に動作したか確認しましょう。
・JavaScriptでJSONのオブジェクトを返却してするVB/C#で取得する場合は、JSON.stringify()
で変換せず、そのままオブジェクトをreturnしてください。
JSON.stringify()で変換すると、VB/C#側で受け取ったデータの先頭と末尾に”が挿入されているので、使いづらいです。
Webページの表示時にJavaScriptを実行する方法
AddScriptToExecuteOnDocumentCreatedAsync
メソッドを使うと、
ページが表示されるときに実行するJavaScriptコードを追加できます。
WebView2の初期化後に、実行したいJavaScriptコードをAddScriptToExecuteOnDocumentCreatedAsync
メソッドで設定します。
下記コードでは、ページを表示する度にalertでurlが表示されます。
※ページを読み込む度にスクリプトが実行されるようになりますので、フレームを使ったページ等は複数回スクリプトが実行されます。
Private Async Sub InitializeAsync() Await WebView2.EnsureCoreWebView2Async(Nothing) Await WebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("alert(window.document.URL);") End Sub
async void InitializeAsync() { await webView2.EnsureCoreWebView2Async(null); await webView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("alert(window.document.URL);"); }
アプリ実行時にWebView2でエラーが発生する場合
アプリ実行時にWebView2コントロールでSystem.NullReferenceException
が発生する場合は、以下を確認してください。
・WebView2ランタイムまたはEdge(Canaryチャネル)がインストールされているか。
・WebView2ランタイムではなくEdge(Canaryチャネル)をインストールしている場合、最新のバージョンとなっているか。
・WebView2の初期化が完了してからアクセスしているか。(WebView2の初期化の待機)
・Edgeが64bitであれば、プロジェクトのプロパティで「32ビットを優先」は外して、64ビットアプリがビルドされるようにしているか。
参考