WebBrowserからWebView2への切り替え
WebBrowserからWebView2への切り替え方法
以前はC#/VB.NETで使用するWebブラウザコントロールはWebBrowserが使われていましたが、
IE11ベースのWebBrowserではサイトが表示できなくなってきていますので、
新しいChromiumベースのWebView2コントロールに切り替えをおすすめします。
WebBrowserとWebView2ではプログラムの方法が色々と異なりますので、
ここではWebBrowserからWebView2に切り替える際のポイントについて解説します。
フォーム画面へのコントロール配置について
WebBrowserもWebView2もVisualStudioのデザイナでフォーム画面に張り付ければよいのですが、
WebView2はデフォルトではツールボックスに存在しないので、追加する必要があります。
WebView2ランタイムのインストール
ここから
WebView2ランタイムの「Evergreen Bootstrapper」をインストールしましょう。
Windows11の場合は最初からWebView2ランタイムが入っていますので、インストールは不要です。

WebView2 SDKのインストール
NuGetから「WebView2」のSDKをインストールします。
メニューの[ツール]->[NuGetパッケージマネージャー]->[ソリューションのNuGetパッケージの管理]を選択します。

検索欄に「WebView2」を入力し、右側で適用するプロジェクトを選択してインストールします。
バージョンは最新の安定版のものを選びます。

しばらく待てばツールボックスにWebView2が現れました。
表示されない場合はVisualStudioを再起動してください。

WebView2の初期化処理
WebView2コントロールはプログラムで初期化が必要です。
WebView2を使用する前までにWebView2.EnsureCoreWebView2Asyncメソッドを実行してください。
Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load InitializeAsync() End Sub Private Async Sub InitializeAsync() Await wv2.EnsureCoreWebView2Async(Nothing) End Sub
public Form1()
{
InitializeComponent();
InitializeAsync();
}
async void InitializeAsync()
{
await wv2.EnsureCoreWebView2Async(null);
}
基本的なブラウザ操作について
基本的なブラウザの操作(ページを開く、進む、戻る、リロード、等)はWebBrowserと同じようなメソッドがあります。
単純に書き換えれば動作します。
以下が対応表です。
| WebBrowser | WebView2 | |
|---|---|---|
| ページを開く | wb.Navigate("") | wv2.CoreWebView2.Navigate("") |
| 戻る | wb.GoBack() | wv2.GoBack() |
| 進む | wb.GoForward() | wv2.GoForward() |
| 読み込み中止 | wb.Stop() | wv2.Stop() |
| リロード | wb.Refresh() | wv2.Reload() |
| タイトルの取得 | wb.Document.Title | wv2.CoreWebView2.DocumentTitle |
| URLの取得 | wb.Document.Url | wv2.CoreWebView2.Source |
ページの表示待ち方法
ページの読み込み完了を待機する処理として、WebBrowserではIsBusyとReadyStateプロパティをループでチェックするのが
主流でしたが、WebView2にはこれらプロパティはありません。
以下のサンプルのようにNavigationCompletedの発生を待つ方法があります。
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();
}
}
DOMの操作方法について
WebBrowserコントロールではDOM操作が行えるメソッド/プロパティがありましたが、
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操作)」を参照してください。
