WebView2の利用方法について、IEとEdgeの処理の違いを中心に似たような記事を書いた。
→[C#] WebBrowserコントロールからWebView2への切り替え
でも、作成したexeファイルをC:\Program Files配下で動作させようとした場合、書き込み権限がなく例外が発生。
アクセスが拒否されました。(HRESULTからの例外:0x80070005(E_ACCESSDENIED))
今回はこの問題を回避しつつ、記事を最新化したので、再び備忘録としてまとめなおし。
<前提>
・Visual Studio 2022
・C#
・Windowsフォーム
・.NET Framework 4.8
この前提でWebブラウザコントロールを、IE(WebBrowser)ではなく、Edge(WebView2)を利用
基本的には上記で試したけど、Visual Studio 2019、VB.NET、WPF、.NET Coreなども同様と思われる。
WebView2ランタイムのインストール
開発環境のPCにWebView2ランタイムをインストール。
Microsoft Edge WebView2
「エバーグリーン ブートストラップ」の「ダウンロード」をクリックしインストール。
WebView2 SDKのインストール
作成するアプリケーションにWebView2をインストール。
- 作成済みのWindowsフォームアプリのソリューションをVisual Studioで開く
- WebView2をインストール
①[ツール]>[NuGetパッケージマネージャ]>[ソリューションのNuGetパッケージ管理]メニューを選択
WebView2をアプリケーションに組み込む
- ツールボックスから「WebView2」コントロールを選びフォームに貼り付ける。
- WebView2のCoreWebView2InitializationCompletedのイベントを作成
- 以下のソースを貼り付ける。
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; using System.IO; using System.Diagnostics; namespace WebView2Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); InitializeAsync(); } async void InitializeAsync() { // アプリ用のフォルダ string localAppFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\TEST\"; if (!File.Exists(localAppFolder)) { Directory.CreateDirectory(localAppFolder); } try { var webView2Environment = await Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(null, localAppFolder); await webView21.EnsureCoreWebView2Async(webView2Environment); } catch (Exception ex) { DialogResult rs = MessageBox.Show("WebView2ランタイムが見つかりません。\n(" + ex.Message + ")\n\nMicrosoft Edge WebView2をインストールしても宜しいですか?", Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (rs == DialogResult.Yes) { // WebView2ランタイムのダウンロード string tmpPath = localAppFolder + @"tmp\"; string installerPath = tmpPath + "MicrosoftEdgeWebview2Setup.exe"; Directory.CreateDirectory(tmpPath); System.Net.WebClient wc = new System.Net.WebClient(); wc.DownloadFile("https://go.microsoft.com/~/", installerPath); // ←★ダウンロード先URLを指定(後述) wc.Dispose(); // インストール実行 Process proc = new Process(); proc.StartInfo.FileName = installerPath; proc.StartInfo.Arguments = @"/install"; proc.Start(); proc.WaitForExit(); System.IO.Directory.Delete(tmpPath, true); Application.Restart(); } this.Close(); } } private void webView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e) { webView21.CoreWebView2.Navigate("https://www.osadasoft.com/"); } } }
- 20行目
webView2コントロールの初期化は非同期で少し時間が掛かるため、後続のInitializeAsyncメソッドで待機。 - 25~29行目
作成したexeファイルの配布を考えた場合、C:\Program Files(x86)配下で動作させたい。
しかし、Program Files配下はアプリから書き込み権限がないため、WebView2が動作できない。
WebView2のDLLがキャッシュファイルを作成できず例外が発生する。アクセスが拒否されました。(HRESULTからの例外:0x80070005(E_ACCESSDENIED))
この例外がでないようアプリ用のフォルダを作成する。
例)C:\Users\UserName\AppData\Local\TEST\書き込みができるパスがあれば良いので、以下のような一時フォルダ等でもOK。
string localAppFolder = System.IO.Path.GetTempPath() + @"tmp\";
- 33,34行目
EnsureCoreWebView2Asyncメソッドで初期化が完了を待機。
WebView2がキャッシュ書き込み等で利用するフォルダは25行目で設定したフォルダ。 - 38~59行目
作成したexeを他のPCに持って行きWebView2ランタイムがインストールされていない環境で実行すると、34行目で以下のような例外が発生する。
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ランタイムは最初からインストールされているのでWebView2のインストールは不要となる。
この例外が発生したとき、WebView2ランタイムのインストールを促す処理をcatchで実行。
- 47行目
ダウンロード用のURLは以下より取得する。<Evergreen WebView2 Runtime ブートストラップのリンクを取得する>
[WebView2 ランタイムをダウンロード] > [エバーグリーン ブートストラップ] > [リンクを取得する]
- 63~66行目
WebView2コントロールのURLを設定。
WebView2の初期化には若干時間がかかる。
IEコントロール(WebBrowser)のように、FormのLoad時にいきなり呼び出そうとすると、例外が発生するため、
WebView2の初期化が完了してから(WebView2のCoreWebView2InitializationCompleted)実行する。
- 20行目
これで完了。
C:\Program Files配下に設置しても問題なく動くようになった。
<追記>
他のPCに配布して実行しようとしたとき、以下の例外が出て少しハマったので追記。
Unable to load DLL ‘WebVIew2Loader.dll’ or one of its dependencies:
指定されたモジュールが見つかりません。(0x8007007E)
ネットで調べてみると、旧バージョンの場合はバグがあり、ファイルパスに「#」や、日本語が混じっているとこのような事象になるとのこと。
でも、Nugetで最新版を適用しなおしても変わらず。
結局、配布DLLが漏れていたことが原因だった。(runtimesフォルダをごっそり忘れていた)
ので覚書。
├runtimes │├win-arm64 ││└native ││ └WebView2Loader.dll │├win-x64 ││└native ││ └WebView2Loader.dll │└win-x86 │ └native │ └WebView2Loader.dll ├Microsoft.Web.WebView2.Core.dll ├Microsoft.Web.WebView2.WinForms.dll ├Microsoft.Web.WebView2.Wpf.dll ├sample.deps.json ├sample.dll ├sample.dll.config ├sample.exe └sample.runtimeconfig.json
デバッグでは動くのに、配布で動かず5時間沼でした。
おかげで解決しました!
ありがとうございます。