C# WebView2.ExecuteScriptAsync()のいくつかの使い方とDebug方法
先日はHTMLページのスクリプトとWebView2の間の通信について触れました。
HTMLページそのものは自分が作成したもので、よってスクリプトも自分の好きなようにHTMLファイルで指定できました。
しかし、もしページが自分のサイトでない場合、最初からページスクリプトの指定ができないため、拡張機能のようにContent Scriptをinjectしなければなりません。
WebView2はExecuteScriptAsync
メソッドを提供していますので、いくつかの基本的な使い方を試したいと思います。
目次
- WebView2.ExecuteScriptAsyncメソッドの定義
- テスト環境の準備
- WebView2.ExecuteScriptAsyncメソッドの使い方
ExecuteScriptAsync
を使うときのDebug方法- 感想
WebView2.ExecuteScriptAsyncメソッドの定義
Task<string> ExecuteScriptAsync (string javaScript);
現在WebView2に表示されているページにstring javaScript
をinjectして実行する。
実行の結果をawait
すればJSONエンコードされたstring
が返される。
テスト環境の準備
- Visual Studio Community 2022
- WinForms プロジェクト@.Net 5
- WebView2を初期化するasync void InitWebViewAsync() {//WebView2を初期化する await wv2.EnsureCoreWebView2Async(null); }
- WebView2にgoogle.comをテストに表示させる(ありがとうGoogle)const string URL = "https://www.google.com"; wv2.Source = new Uri(URL);
WebView2のNavigationCompleted
イベント後であることを確認
WebView2.ExecuteScriptAsyncメソッドの使い方
1. Script文字列をそのまま実行、戻り値なし。例:<body>
背景色を変更
- C#コード
//Script文字列をそのまま実行、戻り値なし、bodyの背景色を変える
await wv2.ExecuteScriptAsync("document.querySelector(\"body\").style.backgroundColor=\"lightgreen\"");
- 実行結果:
2. Script文字列をそのまま実行、戻り値あり。例:HTML取得
- C#コード
//Script文字列をそのまま実行、戻り値あり、Googleのロゴ<img>のHTMLを取得する
string html = await wv2.ExecuteScriptAsync("document.querySelector(\"img[alt='Google']\").outerHTML");
//JSONエンコードのstringから普通のstringに変換
html=System.Text.Json.JsonDocument.Parse(html).RootElement.GetString();
Debug.WriteLine("HTML:");
Debug.WriteLine(html);
- 結果出力
HTML:
<img class="lnXdpd" alt="Google" height="92" src="/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" srcset="/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png 1x, /images/branding/googlelogo/2x/googlelogo_color_272x92dp.png 2x" width="272" data-atf="1" data-frt="0">
- ポイント
ExecuteScriptAsync
で取得したHTMLのstringは"JSONエンコード"されたもので、ブラウザーが認識する普通のstringに変換が必要。
3. JavaScriptファイルを読み込んで実行、戻り値あり。例:<img>
のsrc
を取得
getSrc.js
ファイル
getSrc();
function getSrc() {
let img = document.querySelector("img[alt='Google']");
return img.src;
}
- C#コード
string scriptGetSrc = File.ReadAllText(".\\getSrc.js");
string src= await wv2.ExecuteScriptAsync(scriptGetSrc);
Debug.WriteLine("src:");
Debug.WriteLine(src);
- 結果出力
src:
"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"
4. JavaScriptファイルを読み込んで実行、戻り値あり、JS側パラメーターあり。例:C#で背景色を指定してJS側で変更
setBackColor.js
ファイル
setBackColor(color);
function setBackColor(c) {
let body = document.querySelector("body");
debugger;//debugのため
body.style.backgroundColor = c;
return "bodyの色を" + c + "に設定しました。";
}
- C#コード
// 戻り値あり、引数を必要とする関数をjsファイルから実行
Color randomColor = Color.FromArgb(new Random().Next(0, Int32.MaxValue));
string colorString = $"#{randomColor.R:X2}{randomColor.G:X2}{randomColor.B:X2}";
string scriptSetColor = File.ReadAllText(".\\setBackColor.js");
string result = string.Empty;
if (isFirstRun)//isFirstRunは別途定義
{
result = await wv2.ExecuteScriptAsync($"let color=\"{colorString}\";{scriptSetColor}");
isFirstRun = false;
}
else
{
result = await wv2.ExecuteScriptAsync($"color=\"{colorString}\";setBackColor(color);");
}
Debug.WriteLine("result:");
Debug.WriteLine(result);
- 結果出力
<body>
の背景色を変更したうえ、以下を出力:
result:
"bodyの色を#BBE59Bに設定しました。"
- ポイント
ExecuteScriptAsync
の引数にlet color=\"{colorString}\";
を足すことで、JS側にcolor
を渡すことが可能です。
ただし、一回実行すると、変数color
は既にメモリに存在するため、2回目以降も再度定義しようとするとエラーになります。
よって、1回目の実行かどうかの判断をしたうえで、2回目以降なら、color
を定義するのではなく、値を変えるだけにします。
ExecuteScriptAsync
を使うときのDebug方法
- 課題
ExecuteScriptAsync
でinjectされたスクリプトはファイルでの存在ではないため、DevToolsのSourceタブで見つかりません。
Break Pointを設定してDebugするのにまずDevToolsでJSコードを見つけ出す必要があります。 - 方法1:JSコードに
console.log();
を入れてそこからさかのぼる
例えばJSコードにconsole.log("I am here!");
を入れたら、DevToolsのConsoleタブで以下のように表示されます。 そこでファイル名をクリックしたらinjectされたJSコードにたどり着きます、そこでbreak pointを設置したりできます。 - 方法2
debugger
文を使う
上記4.の例のように、JSコードにdebugger
文を入れれば、DevToolsが開いているときに自動的にそこでブレイクしますので、Console出力からさかのぼって探す必要がなくなります。 また、Call Stackからさらにコール元を追跡することができます。
感想
WebView2.ExecuteScriptAsync
メソッドは便利です。
簡単なJSコードでしたらそのまま実行し、ちょっと長いコードはVisual Studio Code等でまず書いてWebViewで読み込めばいいです。
その場合はVSCodeの自動完成や文法チェック機能も利用できますし、JSコードを少々変更してもC#アプリを再度コンパイルする必要もありません。
先日ブラウザーの拡張機能を作る記事を書きましたが、WebView2でも同じようなことができそうです。
Content Scriptはもちろん、C#側のWebView2でBackground.jsの役割を担えます。
さらに.Netのライブラリも使えますので、可能性が広がります。
今後はシナリオによってうまく使い分けできたらいいなと思います。
コメント
コメントを投稿
個人情報を記入しないようご注意ください