[C#] WebBrowserコントロールからWebView2への切り替え

C#、VB.NET等で標準で使用できるWebブラウザ用の部品として、昔からWebBrowserを使用してきたけど、これがInternet Explorerベースの古い部品。

しかもIE7ベース。
これをIE11ベースに無理やり切り替える方法も昔試していた。

[C#] WebBrowserコントロールのレンダリングモードをデフォルトのIE7から最新IEモードに変更する

けど、さすがにIE11も限界。
 

最近のHTML5やJavaScriptを使用したページが表示できなかったり、セキュリティ更新もできなかったり問題が多すぎる。

そこで、今回最新ブラウザWebBrowserからWebView2への切り替えを試してみたので覚え書き。
(ここではWindowsフォームアプリケーションを例にしていますが、WPFアプリケーションも同様)

WebBrowserはIEベースだったけれども、このWebView2コントロールはMicrosoft Edge(Chromium)ベースでGoogle Chromeとほぼ同等。
WebView2の詳細は以下を参照。
Microsoft Edge WebView2 の概要

 
 

WebView2ランタイムのインストール

まずは、開発環境のPCにWebView2ランタイムをインストール。

Microsoft Edge WebView2

「エバーグリーン ブートストラップ」の「ダウンロード」をクリックしインストール。

 
 

WebView2 SDKのインストール

次に、作成するアプリケーションにWebView2をインストール。
ここでは、C#によるフォームアプリケーションの新規作成も兼ねてWebView2のインストール方法を示します。

  1. Visual Studioを起動し、フォームアプリケーションのプロジェクトを新規作成。
    ①Visual Studioを起動
    ②新しいプロジェクトの作成
    ③フォームアプリケーションを選択し[次へ]ボタン

    ④保存先と.NET Frameworkのバージョンを選択し[作成]ボタン

     

  2. 作成したプロジェクトにWebView2をインストール。
    ①[ツール]>[NuGetパッケージマネージャ]>[ソリューションのNuGetパッケージ管理]メニューを選択

    ②パッケージソースで「nuget.org」を選択して、「参照」タブを選び、「WebView2」を検索しインストール

     

 
 

WebView2をアプリケーションに組み込む

  1. ツールボックスから「WebView2」コントロールを選びフォームに貼り付ける。
    「WebBrowser」コントロールも比較用として、ついでに貼り付ける。

  2. 以下のソースを貼り付ける。
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            string url = ”https://www.osadasoft.com/”;
    
            public Form1()
            {
                InitializeComponent();
                InitializeAsync();
            }
    
            async void InitializeAsync()
            {
                try
                {
                    await webView21.EnsureCoreWebView2Async(null);
                }
                catch (Exception)
                {
                    MessageBox.Show("WebView2ランタイムがインストールされていない可能性があります。", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    this.Close();
                }
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                webBrowser1.ScriptErrorsSuppressed = true;
                webBrowser1.Url = new Uri(url);
            }
    
            private void webView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
            {
                webView21.CoreWebView2.Navigate(url);
            }
        }
    }
    

 

上記C#ソースについて少し補足。

  • 20行目
    webView2コントロールの初期化は非同期で少し時間が掛かるため、後続のInitializeAsyncメソッドで待機。
     

  • 27行目
    EnsureCoreWebView2Asyncメソッドで初期化が完了を待機。

    ちなみに、作成したexeを他のPCに持って行きWebView2ランタイムがインストールされていない環境で実行すると、以下のような例外が発生する。

    Unhandled exception has occurred in your application.
    If you click Continue, the application will ignore this error and attempt to continue.
    If you click Quit, the application will close immediately.
    Object refarence not set to an instance of an object.

    さらに、ちなみに、Windows 11からはWebView2ランタイムは最初からインストールされているようなので、今後はあまり気にしないで良くなる模様。
     

  • 25~33行目
    上記例外が出るのは格好悪いので、例外が出ないようtry-catchで括り、WebView2ランタイムが無いとわかるような警告メッセージボックスを表示してアプリケーションを終了させる。

     
    →単なる警告ではなく、WebView2ランタイムのインストールを促したい場合、下記「おまけ2」を参照。
     

  • 38、39行目
    こちらは、比較用のWebBrowserコントロール。
    初期化は特に時間が掛からないため、普通にFormのLoad時に処理をいきなり書くことが出来る。
     

  • 42~45行目
    WebView2コントロールのURLを設定。
    こちらは、初期化に時間がかかり、FormのLoad時に呼び出すと例外が発生するため、WebView2の初期化が完了したときに発生するイベント(WebView2のCoreWebView2InitializationCompleted)の処理内で実行する。

 
 

実行確認

  1. [F5]でビルド&実行。

     ⇒同じサイトを表示した結果。
     [画面下側]WebBrowser(IE)では表示できないが、[画面上側]WebView2(Edge)では正常に表示することができた。

 
 

作成アプリの配布方法

WebView2を使用したアプリケーション(exe)を他のPCに配布する場合、配布先PCにもWebView2ランタイム(再配布可能)が必要となる。
※Windows11の場合は標準インストールされている

WebView2ランタイムは、Evergreen配布、固定バージョン配布の2種類があり、
前者はPC内で1つ最新ブラウザが使用され、
後者はアプリごと固定バージョンのブラウザが使用される。
通常は前者を使用する。説明を端折り過ぎなので詳細は、以下を参照。
[Microsoft]ランタイム、Evergreen 配布、および固定バージョンの配布の概要

で、Evergreen配布の場合、作成したアプリ実行前に配布先PCにWebView2ランタイムをインストールする必要がある。

Microsoft Edge WebView2

「エバーグリーン ブートストラップ」の「ダウンロード」をクリックしインストール。

と言っても、アプリ利用者側にはダウンロード&インストールの手間がかかる。
アプリ内でレジストリを確認しインストール済みかチェックし、無ければサイレントインストールする方法もある。
詳細はこちら。→[Microsoft]エバーグリーン WebView2 ランタイムの展開

そして、今度は作成したアプリ側の準備。
作成したexeファイルだけでは動作しない。
ビルド時に生成された以下のファイルも一緒に配布する必要がある。

runtimes\win-arm64\native\WebView2Loader.dll─┐
runtimes\win-x64\native\WebView2Loader.dll    ├─ビルド時に
runtimes\win-x86\native\WebView2Loader.dll    │  自動生成される
Microsoft.Web.WebView2.Core.dll               │
Microsoft.Web.WebView2.WinForms.dll           │
Microsoft.Web.WebView2.Wpf.dll              ─┘
WindowsFormsApp1.exe                        ─┬─作成アプリ(sample)
WindowsFormsApp1.exe.config                 ─┘

 
 

おまけ1

この対応(IE→Microsoft Edge)を、画像位置情報取得ツールに対しても行いました。
 
 

おまけ2

WebView2ランタイムがインストールされていない環境で実行された場合に、WebView2ランタイムをダウンロード&インストールさせたい場合は以下の通り。
上記、ソースのcatch文(29~33行目)を書き換える。

catch (Exception)
{
    DialogResult rs = MessageBox.Show(
        "WebView2ランタイムが見つかりません。\n\nインストールしますか?",
        Application.ProductName,
        MessageBoxButtons.YesNo,
        MessageBoxIcon.Question);
    if (rs == DialogResult.Yes)
    {
        // WebView2ランタイムのダウンロード
        string downloadUrl = "https://go.microsoft.com/~"; // ←★ダウンロード先を指定
        System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetEntryAssembly();
        string tmpInstPath = Path.GetDirectoryName(myAssembly.Location) + @"\ + "tmp";
        string installerPath = tmpInstPath + @"\MicrosoftEdgeWebview2Setup.exe";
        Directory.CreateDirectory(tmpInstPath);
        System.Net.WebClient wc = new System.Net.WebClient();
        wc.DownloadFile(downloadUrl, installerPath);
        wc.Dispose();

        // インストール実行
        Process proc = new Process();
        proc.StartInfo.FileName = installerPath;
        proc.StartInfo.Arguments = @"/install";
        proc.Start();
        proc.WaitForExit();
        System.IO.Directory.Delete(tmpInstPath, true);
        Application.Restart();
    }
    this.Close();
}

↑39行目のダウンロード先URLは、Microsoft Edge WebView2より取得する。

<Evergreen WebView2 Runtime ブートストラップのリンクを取得する>
[WebView2 ランタイムをダウンロード] > [エバーグリーン ブートストラップ] > [リンクを取得する]

 
 

おまけ3

アクセス権限が問題ないフォルダでは、上記記事で問題なく動作していた。
けど、このアプリをC:\Program Files配下に設置し、実行すると以下のような例外が発生することが判明。

アクセスが拒否されました。(HRESULTからの例外:0x80070005(E_ACCESSDENIED))

Windows Vistaで追加されたUAC(Windowsのユーザーアカウント制御)辺りから、Program Files配下へのファイル書き込みは推奨されないとはなっていたけど、今までVirtualStoreフォルダに勝手に書き込まれる機能で動作していた。(ような気がする)

ここにきて(Windows11?)、うまく回避できなくなってきたみたい。
WebView2を使用しているアプリを実行すると、WebView2関連のDLLは書き込めるようだけど、キャッシュファイル等は書き込めず、上記例外が発生してしまう。

単純にC:\Program Files以外に、アプリを置いてもらえば良いのだが、それも気持ち悪い。
ということで、C:\Program Files配下でも正常動作するよう回避してみました。
アプリ配布を考えている方は、こちらを参考にしてみてください。

[C#] WebView2コントロールの利用方法

 
 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


*