内藤 裕二/ 2024年 3月 28日/ 技術

こんにちは!内藤です!
春ですね!雪割りで腰が痛いです。。。

久しぶりにWPFでWebView2を触る機会があったので、備忘録的にまとめておきます

TL;DR;

  • インストール
  • 初期表示のタイミング
    • Visual StudioのプロパティウィンドウからSourceプロパティを設定しない
  • キャッシュとユーザフォルダ
    • キャッシュ残したい場合は指定する
    • 指定する場合は、書き込み権限に注意する
  • プロキシ設定
    • 認証なし
    • 認証あり(BASIC認証)

勘所

インストール

インストールとプロジェクトのセットアップは、公式に従って、特に引っかかることなくできました。

初期表示のタイミング

VisualStudioのプロパティウィンドウからSourceプロパティを設定してしまうと、その後プログラムから変更できないケースがあるようです。
また、特定のURLを表示するだけなら良いのですが、そうでない場合、いくつか初期設定を行う必要があります。
後々の初期化を想定して、WindowクラスのContent_RenderedイベントハンドラでWebView2のSourceプロパティを設定します。

        /// <summary>
        /// 初期表示URL
        /// </summary>
        public string FirstUrl { get; set;}

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            // WebView2で初期表示
            this.webView2.Source = new Uri(this.FirstUrl);
        }

キャッシュとユーザフォルダ

WebView2を起動すると、ローカルに数10MB程度のキャッシュをため込みます。
このキャッシュには、ユーザの入力履歴等も含まれます。
キャッシュを保存するフォルダを指定できることができるのですが、指定の仕方が非常にわかりにくいです。

初期表示の前に、ブラウザの環境設定を行う必要があります。
下記のようなコードになります。

        /// <summary>
        /// 初期表示URL
        /// </summary>
        public string FirstUrl { get; set;}

        /// <summary>
        /// ユーザフォルダパスを設定する
        /// </summary>
        public string WebUserFolderPath { get; set;}

        private async void Window_ContentRendered(object sender, EventArgs e)
        {
            var url = "https://www.google.com";

            // WebView2の設定
            CoreWebView2Environment env = null;
            CoreWebView2EnvironmentOptions Options = new CoreWebView2EnvironmentOptions();

            // ユーザフォルダを指定してWevView2用の環境を適用する
            env = await CoreWebView2Environment.CreateAsync(null, this.WebUserFolderPath, Options);
            await webView2.EnsureCoreWebView2Async(env);

            // WebView2で初期表示
            this.webView2.Source = new Uri(this.FirstUrl);
        }

ここで指定するフォルダは、アプリケーションの実行ユーザが書き込み権限を持っている必要があります。
実行フォルダ直下とかにすると、「Program Files」配下とかにアプリケーションをインストールした際に問題になることがあるので、注意が必要です。

プロキシ設定

認証なし

C#でプロキシを使用する場合、IWebProxyインターフェイス継承クラスを使用することが多いと思います。
残念ながら、WebView2はIWebProxyをそのまま渡せないので、アプリケーション側で設定する必要があります。
ユーザフォルダ指定と同じようなタイミングで、プロキシ情報を設定します。

        /// <summary>
        /// 初期表示URL
        /// </summary>
        public string FirstUrl { get; set;}

        /// <summary>
        /// WebPrxy情報を設定する
        /// </summary>
        public IWebProxy WebProxy { get; set;}

        private async void Window_ContentRendered(object sender, EventArgs e)
        {
            // WebView2の設定
            CoreWebView2Environment env = null;
            CoreWebView2EnvironmentOptions Options = new CoreWebView2EnvironmentOptions();

            if (this.WebProxy != null)
            {
                var target_uri = new Uri(this.FirstUrl);
                var proxyurl = this.WebProxy.GetProxy(target_uri);
                if (proxyurl == null || proxyurl.ToString() == target_uri.ToString())
                {
                    // プロキシ不要
                }
                else
                {
                    // 指定されたプロキシを適用する
                    var proxyuri_str = proxyurl.ToString();
                    if (proxyuri_str.EndsWith("/"))
                    {
                        proxyuri_str = proxyuri_str.Substring(0, proxyuri_str.Length - 1);
                    }
                    Options.AdditionalBrowserArguments = "--proxy-server=" + proxyuri_str;
                }
            }

            // プロキシを指定してWevView2用の環境を適用する
            env = await CoreWebView2Environment.CreateAsync(null, null, Options);
            await webView2.EnsureCoreWebView2Async(env);

            // WebView2で初期表示
            this.webView2.Source = new Uri(this.FirstUrl);
        }

認証あり

プロキシに認証情報を渡す場合は、WebView2のCoreWebView2オブジェクトにイベントハンドラを設定する必要があります。
BASIC認証のプロキシで試していますので、プロキシがその他の認証方式の場合は、別の方法が必要かもしれません。

        /// <summary>
        /// 初期表示URL
        /// </summary>
        public string FirstUrl { get; set;}

        /// <summary>
        /// WebPrxy情報を設定する
        /// </summary>
        public IWebProxy WebProxy { get; set;}

        private async void Window_ContentRendered(object sender, EventArgs e)
        {
            // WebView2の設定
            CoreWebView2Environment env = null;
            CoreWebView2EnvironmentOptions Options = new CoreWebView2EnvironmentOptions();

            if (this.WebProxy != null)
            {
                var target_uri = new Uri(this.FirstUrl);
                var proxyurl = this.WebProxy.GetProxy(target_uri);
                if (proxyurl == null || proxyurl.ToString() == target_uri.ToString())
                {
                    // プロキシ不要
                }
                else
                {
                    // 指定されたプロキシを適用する
                    var proxyuri_str = proxyurl.ToString();
                    if (proxyuri_str.EndsWith("/"))
                    {
                        proxyuri_str = proxyuri_str.Substring(0, proxyuri_str.Length - 1);
                    }
                    Options.AdditionalBrowserArguments = "--proxy-server=" + proxyuri_str;
                }
            }

            // プロキシを指定してWevView2用の環境を適用する
            env = await CoreWebView2Environment.CreateAsync(null, null, Options);
            await webView2.EnsureCoreWebView2Async(env);

            // 認証情報を求められたら、設定された認証情報を設定する
            if (this.WebProxy != null)
            {
                // プロキシの認証情報を詰める
                webView2.CoreWebView2.BasicAuthenticationRequested += new EventHandler<CoreWebView2BasicAuthenticationRequestedEventArgs>(delegate (object source, CoreWebView2BasicAuthenticationRequestedEventArgs evtarg)
                {
                    // 渡されたWebProxyから認証情報を取得して設定する
                    var credentials = this.WebProxy.Credentials as NetworkCredential;
                    if (credentials != null)
                    {
                        evtarg.Response.UserName = credentials.UserName;
                        evtarg.Response.Password = credentials.Password;
                    }
                });
            }

            // WebView2で初期表示
            this.webView2.Source = new Uri(this.FirstUrl);
        }

参照URL