WebView2の触り

WebView2って?

WebView2の触りの記事はいくつかあるのですが、私も触ってみましたので、少しメモです。

WebView2はMicrosoft Edgeのレンダリングエンジンであり、Edge=Chromiumを介してウェブコンテンツを表示できます。 要はMicrosoft謹製のElectronみたいなことができる、というテクノロジです。 Windows系のネイティブAPIやC#などの.NET系と連携しやすくなっているのがポイントです。 最近はMicrosoftはWindows組み込みアプリにやたらこのテクノロジを推進していて、TeamsやOutlookなどに採用し、Webアプリ版とのソースコードの統合・UXの改善・パフォーマンス向上などを狙っているみたいです。

Windows系でネイティブのdllが読めればいいので(結構面倒なので内部的にライブラリとか介したりするんですが)、 他言語でもこのテクノロジは内部的には使っていて、RustのTauriやPythonのPywebviewのようなフレームワークが利用しています。

導入

WPFでの例を紹介します。

Microsoft.Web.WebView2をNugetからインストールすると、WebView2コントロールが利用できるようになります。
まだ自分がやってるのはNodeベースのサーバを立ち上げてローカルホストを読む手法です。file://プロトコルを使ってもいいです。 本来、スタートアップスクリプトでASP.NETのサーバを立ち上げて連携させるのが良い手段なのでしょう。

<Wpf:WebView2 x:Name="WebViewPanel" Source="http://localhost:5173" />

ビルドしたものは、WebView2Loader.dllが上手く読み込まないことがあります。これはWebView2の超めんどい仕様です。この際、csprojPlatformTargetを設定すると上手く行きやすいので設定します

<PlatformTarget>x64</PlatformTarget>

データのメッセージング

WebView2コントロールで展開されたDOMにはwindow.chrome.webviewいうプロパティが追加されており、これを使うことがホスト・フロント間メッセージングの中心になります。

private void MyControl()
{
    webView.WebMessageReceived += webView_WebMessageReceived;
    webView.NavigationCompleted += webView_NavigationCompleted;
}

private void webView_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs e)
{
    // e.WebMessageAsJson javascriptオブジェクトが渡された時
    var s = e.TryGetWebMessageAsString(); // 文字列が渡された時
    MessageBox.Show(s);
}

private void webView_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
{
    // webView.CoreWebView2.PostWebMessageAsJson(jsonStr);
    webView.CoreWebView2.PostWebMessageAsString("hello from C#!");
}

スクリプトメッセージング

ElectronでいうexposeInMainWorld()みたいなことをする場合、AddHostObjectToScript()によってwindow.webview.hostObjectsにオブジェクトが拡張されます。これは拡張されたプロパティが全てProxyなのでデバッグはやりにくいように見えますが、ともかくもこれでやりとりが可能です

using System.Runtime.InteropServices;

[ComVisible(true)]
public class Test
{
    public int Count { get; set; } = 100;
    public void HelloWorld(string value)
    {
        MessageBox.Show($"Hello: {value}");
    }
}

private Test _test = new Test();

// オブジェクトの公開
WebViewPanel.CoreWebView2.AddHostObjectToScript("test", _test);
// javscriptスクリプトを実行する
WebViewPanel.CoreWebView2.ExecuteScriptAsync("alert('Hello, World!');");
window.chrome.webview.hostObjects.test.HelloWorld("foo"); // C#メソッドを実行する
await window.chrome.webview.hostObjects.test.Count; // C#プロパティを取得する

やってみて

とりあえず最低限のところはわかったのですが、少しだけまだめんどいな、と思いました。あと情報が少ない。 基本、生産性重視ならElectronを使う方が良いと思います。しかし、C#でDesktop + Webのハイブリッドアプリを作りたい場合、Mauiより案外良い選択肢だと思います。

最近体調崩し中

先月辺りから絶賛喉から胃の体調がすこぶる悪くて、朝とか中々に痛いです。 ワタクシ、あまり病院には行かないのですが、色々支障を来しまくってるので最近行くようになりました。

CTなるものを初めてやったのですが、まあとりあえず悪い腫瘍みたいなのは無いそうなのだけど、食道から胃にかけての形に怪しい感じがある?かもで、 まあ結局耳鼻科や胃腸科行って内視鏡撮った方が良いよと言われることに、、うーん、収穫が、、

ちょっと原因が不明なのですが、本当に悪い感じなのでこれはもう根治したい、、

会社休んじゃうし、かといってじゃあ業務できるかと言ったら微妙になってく、、
有給が溶けてくんで、こういうのはまじで嫌ですね。。