C# WebViewの使い方完全ガイド|WebView2導入から表示・エラー対処まで解説
はじめに
C#でデスクトップアプリを作っていると、「アプリ内にWebページを表示したい」「HTMLで作った画面をWinFormsやWPFに埋め込みたい」「社内WebシステムをC#アプリから開きたい」という場面があります。そこで使われる代表的な仕組みがWebViewです。
現在のC# WebView実装では、従来のWebBrowserコントロールではなく、Microsoft Edge Chromiumをレンダリングエンジンとして使うWebView2を選ぶのが基本です。WebView2を使うと、HTML、CSS、JavaScriptで作られた画面をC#アプリ内に表示でき、さらにC#とJavaScriptを相互に連携させることもできます。MicrosoftのWebView2 APIリファレンスでも、WebView2はChromiumベースのMicrosoft Edgeをレンダリングエンジンとして使い、アプリケーション内でWebコンテンツをホストできるコントロールとして説明されています。
この記事では、C# WebViewの基本から、WebView2の導入、WinForms・WPFでの実装、JavaScript連携、ローカルHTMLの表示、エラー対処、配布方法、セキュリティ設定までを実務向けに解説します。
1. C# WebViewとは?WebView2を使うべき理由
C# WebViewとは、C#で作成したデスクトップアプリの中にWebページやHTMLコンテンツを表示するための仕組みです。たとえば、WinFormsアプリの一部に社内ポータルを表示したり、WPFアプリの画面にHTMLベースのヘルプやダッシュボードを埋め込んだりできます。
現在、C#でWebViewを使う場合は、Microsoft.Web.WebView2パッケージを導入してWebView2コントロールを使うのが一般的です。WebView2には、ナビゲーション、JavaScript実行、Webメッセージング、Cookie、ダウンロード、印刷、コンテキストメニュー、新しいウィンドウ制御など、多くのブラウザー機能にアクセスするAPIが用意されています。
1-1. C#でWebページを表示したいときの選択肢
C#でWebページを表示する方法には、主に次の選択肢があります。
1つ目は、古くからあるWebBrowserコントロールを使う方法です。実装は簡単ですが、古いInternet Explorer系の挙動に依存するため、現代的なWebサイトやJavaScriptフレームワークとの相性がよくありません。
2つ目は、WebView2を使う方法です。Microsoft Edge Chromiumベースの表示エンジンを利用できるため、現在のWeb標準に対応しやすく、C#アプリ内でWebコンテンツを扱う用途に向いています。
3つ目は、外部ブラウザーを起動する方法です。実装は簡単ですが、アプリ内に画面を埋め込むことはできません。ログイン画面、管理画面、帳票ビューア、ヘルプ画面などをアプリ内に統合したい場合はWebView2が適しています。
1-2. 従来のWebBrowserコントロールとWebView2の違い
WebBrowserコントロールとWebView2の大きな違いは、レンダリングエンジンです。WebBrowserは古いIE系のエンジンに依存する一方、WebView2はChromiumベースのMicrosoft Edgeを利用します。MicrosoftのAPIリファレンスでも、WebView2はChromiumベースのMicrosoft EdgeをレンダリングエンジンとしてWebコンテンツをホストすると説明されています。
そのため、WebView2では現代的なHTML、CSS、JavaScriptの表示に対応しやすくなります。たとえば、SPA、社内Webアプリ、レスポンシブデザイン、PDF表示、JavaScriptによるDOM操作などを扱う場合、WebBrowserよりWebView2のほうが実用的です。
また、WebView2はC#側からJavaScriptを実行したり、JavaScript側からC#へメッセージを送ったりできます。単にWebページを表示するだけでなく、ネイティブアプリとWeb画面を組み合わせたハイブリッドアプリを作れる点が大きな特徴です。
1-3. WebView2でできること
WebView2を使うと、C#アプリ内で次のような処理を実装できます。
Webページの表示、戻る・進む・再読み込み、現在のURLやタイトルの取得、ページ読み込み完了イベントの検知、JavaScriptの実行、JavaScriptとC#の双方向通信、ローカルHTMLの表示、PDFや画像の表示、新しいウィンドウの制御、Cookieやキャッシュの管理、DevToolsの制御などです。
特に便利なのは、C#とJavaScriptの連携です。C#側からExecuteScriptAsyncを使ってJavaScriptを実行でき、戻り値はJSONエンコードされた文字列として取得できます。 また、Webページ側でwindow.chrome.webview.postMessageを呼び出すと、C#側のWebMessageReceivedイベントで受け取れます。
1-4. WinForms・WPF・WinUIでの対応範囲
WebView2は、C#のデスクトップアプリでよく使われるWinForms、WPF、WinUIなどに対応しています。MicrosoftのWebView2 APIリファレンスでは、.NET/C#、WinRT/C#、Win32/C++に加えて、WPF、Windows Forms、WinUIなどのプラットフォームが挙げられています。
既存の業務アプリであればWinForms、新規開発で柔軟なUIを作りたい場合はWPF、Windows App SDKを使う場合はWinUIが候補になります。WebView2自体の基本的な考え方は共通ですが、コントロールの配置方法やレイアウトの書き方はフレームワークごとに異なります。
1-5. WebView2を使う前に知っておきたい注意点
WebView2を使うには、開発時にMicrosoft.Web.WebView2 SDKをプロジェクトへ追加するだけでなく、実行環境にWebView2 Runtimeが存在する必要があります。Microsoftの配布ドキュメントでも、WebView2アプリを配布するときはクライアントPCにWebView2 Runtimeが存在することを確認する必要があると説明されています。
また、WebView2はWebコンテンツをアプリ内に表示するため、セキュリティ設計も重要です。外部サイトを表示する場合、JavaScript連携を有効にする場合、ローカルファイルへアクセスさせる場合は、信頼できるURLだけを許可し、受け取るデータを必ず検証する必要があります。Microsoftのセキュリティガイドでも、WebView2内のWebコンテンツはネイティブアプリのリソースやAPIへアクセスできる可能性があるため、適切に分離しないと脆弱性につながると説明されています。
2. C# WebView2の導入準備
WebView2を使うには、Visual Studio、C#プロジェクト、NuGetパッケージ、WebView2 Runtimeの確認が必要です。ここでは、WinFormsまたはWPFでWebView2を使う前の準備を整理します。
2-1. 開発に必要な環境
基本的には、次の環境を用意します。
Visual Studio、C#のWinFormsまたはWPFプロジェクト、Microsoft.Web.WebView2 NuGetパッケージ、WebView2 Runtimeです。
Visual Studioのバージョンは新しいものを推奨します。既存アプリに組み込む場合は.NET Frameworkでも利用できますが、新規開発では.NET 8以降など、サポート期間の長い.NETを選ぶと保守しやすくなります。
WebView2 SDKにはリリース版とプレリリース版があります。Microsoftのバージョン管理ドキュメントでは、運用リリースではリリース版SDKとWebView2 Runtimeの組み合わせを使い、実験的APIを試す場合はプレリリースSDKとEdgeプレビューチャネルを組み合わせると説明されています。
2-2. Visual Studioでプロジェクトを作成する
Visual Studioで新規プロジェクトを作成する場合は、次のいずれかを選びます。
WinFormsなら「Windows フォーム アプリ」、WPFなら「WPF アプリケーション」を選択します。既存の.NET Frameworkアプリへ組み込む場合は、対象フレームワークがWebView2パッケージに対応しているか確認します。MicrosoftのWinForms入門ドキュメントでは、WinFormsプロジェクトにWebView2 SDKをインストールし、WebView2コントロールを追加する手順が紹介されています。
2-3. Microsoft.Web.WebView2をNuGetでインストールする
WebView2を使うには、NuGetでMicrosoft.Web.WebView2をインストールします。
Visual Studioでは、プロジェクトを右クリックし、「NuGet パッケージの管理」を開きます。検索欄にMicrosoft.Web.WebView2と入力し、表示されたパッケージをインストールします。WPFの公式手順でも、NuGetパッケージマネージャーでMicrosoft.Web.WebView2を検索してインストールする流れが説明されています。
パッケージマネージャーコンソールを使う場合は、次のように実行します。
PowerShellInstall-Package Microsoft.Web.WebView2
.NET CLIを使う場合は、次のコマンドです。
Bashdotnet add package Microsoft.Web.WebView2
2-4. WebView2 Runtimeの役割と確認方法
WebView2 SDKは開発時に必要なライブラリです。一方、WebView2 RuntimeはユーザーPCでWebView2を実行するために必要なランタイムです。つまり、開発PCでは動くのにユーザーPCでは動かない場合、WebView2 Runtimeが未インストールであるケースがあります。
WebView2 Runtimeの存在確認は、レジストリキーを確認する方法や、APIでバージョン情報を取得する方法があります。Microsoftの配布ドキュメントでは、pvレジストリキーを確認する方法と、GetAvailableCoreWebView2BrowserVersionStringで確認する方法が紹介されています。
C#では簡易的に次のようなチェックができます。
C#using Microsoft.Web.WebView2.Core;
string? version = CoreWebView2Environment.GetAvailableBrowserVersionString();
if (string.IsNullOrEmpty(version))
{
MessageBox.Show("WebView2 Runtimeがインストールされていません。");
}
else
{
MessageBox.Show($"WebView2 Runtime version: {version}");
}
2-5. Evergreen版と固定バージョン版の違い
WebView2 Runtimeには、大きく分けてEvergreen版と固定バージョン版があります。
Evergreen版は自動更新される共有Runtimeです。Microsoftの配布ドキュメントでは、Evergreen配布モードを使うとWebView2アプリが最新のWebView2機能とセキュリティ更新を利用でき、すべてのWebView2アプリが共有コピーを使うためディスク領域を節約できると説明されています。
固定バージョン版は、特定バージョンのRuntimeをアプリと一緒に配布する方式です。業務アプリで表示結果を厳密に固定したい場合や、更新管理をアプリ側で行いたい場合に向いています。ただし、Runtimeのファイルサイズが増え、セキュリティ更新も自分たちで管理する必要があります。固定バージョンRuntimeでは、Runtimeパッケージを展開し、アプリ配布物に含め、WebView2環境作成時にそのパスを指定します。
一般的な業務アプリではEvergreen版を優先し、オフライン環境や厳格な検証が必要な環境では固定バージョン版を検討するとよいでしょう。
2-6. .NET Frameworkと.NETのどちらを選ぶべきか
既存のWinFormsやWPFアプリが.NET Frameworkで作られている場合は、そのままWebView2を組み込む選択肢があります。既存資産を活かせるため、移行コストを抑えられます。
一方、新規開発であれば、.NET 8以降などの現行.NETを選ぶほうが、今後の保守やライブラリ更新に対応しやすくなります。特に、将来的にWPFやWinFormsの機能拡張、CI/CD、配布方式の改善を考えている場合は、現行.NETを選ぶメリットが大きくなります。
判断の目安は次の通りです。
既存アプリへ最小限の改修でWebView2を追加したいなら.NET Framework、新規開発または大規模改修なら現行.NETを選ぶとよいでしょう。
3. WinFormsでWebView2を使う基本手順
WinFormsでWebView2を使う場合は、フォームにWebView2コントロールを配置し、初期化後にURLやHTMLを表示します。ここでは、最小限の手順でWebページを表示する方法を解説します。
3-1. フォームにWebView2コントロールを追加する
NuGetでMicrosoft.Web.WebView2をインストールすると、Visual StudioのツールボックスにWebView2コントロールが表示されます。フォームデザイナーにドラッグ&ドロップすれば、通常のWinFormsコントロールと同じように配置できます。MicrosoftのWinForms入門でも、ツールボックスからWebView2 Windows Formsコントロールを追加する手順が説明されています。
コードで追加する場合は、次のように書けます。
C#using Microsoft.Web.WebView2.WinForms;
private WebView2 webView = new WebView2();
private void MainForm_Load(object sender, EventArgs e)
{
webView.Dock = DockStyle.Fill;
Controls.Add(webView);
}
3-2. コードでWebView2を初期化する
WebView2は内部のCoreWebView2が初期化されてから操作する必要があります。初期化にはEnsureCoreWebView2Asyncを使います。MicrosoftのWinFormsチュートリアルでも、CoreWebView2の初期化は非同期であるため、EnsureCoreWebView2Asyncを待機する例が紹介されています。
C#private async void MainForm_Load(object sender, EventArgs e)
{
webView.Dock = DockStyle.Fill;
Controls.Add(webView);
await webView.EnsureCoreWebView2Async();
}
CoreWebView2がnullのまま操作しようとすると例外や意図しない動作につながります。URL遷移やJavaScript実行は、必ず初期化後に行いましょう。
3-3. URLを指定してWebページを表示する
Webページを表示するには、SourceプロパティまたはCoreWebView2.Navigateを使います。
C#await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.Navigate("https://example.com");
または、次のようにSourceへUriを設定できます。
C#webView.Source = new Uri("https://example.com");
ユーザーが入力したURLを表示する場合は、http://やhttps://が省略されていないか確認し、不正なURLを弾く処理を入れると安全です。
3-4. ローカルHTMLを表示する
HTML文字列を直接表示する場合は、NavigateToStringを使います。
C#string html = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Local HTML</title>
</head>
<body>
<h1>Hello WebView2</h1>
<p>C#からHTML文字列を表示しています。</p>
</body>
</html>
""";
webView.NavigateToString(html);
単純なヘルプ画面、HTMLプレビュー、帳票の確認画面などは、この方法で簡単に実装できます。
3-5. 表示サイズをフォームに合わせて調整する
WinFormsでは、Dockプロパティを使うとフォームサイズに合わせてWebView2を拡大縮小できます。
C#webView.Dock = DockStyle.Fill;
上部にアドレスバーやボタンを置く場合は、Panelを上部に配置し、WebView2を残り領域にDockStyle.Fillで配置します。
C#var topPanel = new Panel
{
Dock = DockStyle.Top,
Height = 40
};
var webView = new WebView2
{
Dock = DockStyle.Fill
};
Controls.Add(webView);
Controls.Add(topPanel);
3-6. 最小構成のサンプルコード
次のコードは、WinFormsでWebView2を表示する最小構成です。
C#using Microsoft.Web.WebView2.WinForms;
namespace WinFormsWebView2Sample;
public partial class MainForm : Form
{
private readonly WebView2 webView = new();
public MainForm()
{
InitializeComponent();
Load += MainForm_Load;
}
private async void MainForm_Load(object? sender, EventArgs e)
{
webView.Dock = DockStyle.Fill;
Controls.Add(webView);
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.Navigate("https://example.com");
}
}
InitializeComponentが存在しないシンプルな手書きフォームの場合は、次のように書けます。
C#using Microsoft.Web.WebView2.WinForms;
namespace WinFormsWebView2Sample;
public class MainForm : Form
{
private readonly WebView2 webView = new();
public MainForm()
{
Text = "C# WebView2 Sample";
Width = 1000;
Height = 700;
webView.Dock = DockStyle.Fill;
Controls.Add(webView);
Load += async (_, _) =>
{
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.Navigate("https://example.com");
};
}
}
4. WPFでWebView2を使う基本手順
WPFでWebView2を使う場合は、XAMLにWebView2コントロールを配置し、C#コードビハインドから操作します。WinFormsよりレイアウトが柔軟なため、画面の一部にWebコンテンツを埋め込む構成に向いています。
4-1. XAMLにWebView2コントロールを配置する
WPFでは、まずXAMLにWebView2の名前空間を追加します。MicrosoftのWPF入門ドキュメントでも、Microsoft.Web.WebView2.Wpfの名前空間をXAMLに追加し、wv2:WebView2を配置する手順が説明されています。
XML<Window x:Class="WpfWebView2Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
Title="C# WebView2 Sample"
Width="1000"
Height="700">
<Grid>
<wv2:WebView2 x:Name="WebView" />
</Grid>
</Window>
4-2. C#コードからWebView2を操作する
コードビハインドでは、EnsureCoreWebView2Asyncで初期化してから操作します。
C#using System.Windows;
namespace WpfWebView2Sample;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
await WebView.EnsureCoreWebView2Async();
WebView.CoreWebView2.Navigate("https://example.com");
}
}
WPFでもWinFormsと同じく、CoreWebView2が初期化される前にCoreWebView2.NavigateやExecuteScriptAsyncを呼ばないように注意します。
4-3. NavigateメソッドでWebページを表示する
WPFでもURLを指定してWebページを表示するには、Navigateを使います。
C#WebView.CoreWebView2.Navigate("https://example.com");
XAMLのSourceプロパティで初期URLを指定することもできます。MicrosoftのWPF入門でも、SourceプロパティでWebView2コントロールに表示する初期URIを設定する例が紹介されています。
XML<wv2:WebView2 x:Name="WebView"
Source="https://example.com" />
ただし、初期化後にイベント登録や設定変更をしたい場合は、C#側でEnsureCoreWebView2Asyncを待ってから遷移するほうが制御しやすくなります。
4-4. NavigateToStringでHTML文字列を表示する
WPFでもHTML文字列を直接表示できます。
C#string html = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: sans-serif; padding: 24px; }
h1 { color: #333; }
</style>
</head>
<body>
<h1>HTML Preview</h1>
<p>WPFアプリ内にHTML文字列を表示しています。</p>
</body>
</html>
""";
WebView.NavigateToString(html);
Markdownプレビュー、帳票プレビュー、メール本文プレビュー、ヘルプ画面などをWPFアプリ内で表示したい場合に便利です。
4-5. WPFでよくあるレイアウト崩れの対処
WPFでWebView2を配置するときは、親コンテナのサイズ指定に注意します。StackPanelの中にWebView2をそのまま置くと、高さが意図どおりに確保されないことがあります。基本的にはGridを使い、WebView2を*領域に配置するのがおすすめです。
XML<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="AddressBar"
Grid.Row="0"
Margin="4" />
<wv2:WebView2 x:Name="WebView"
Grid.Row="1" />
</Grid>
また、タブUIや画面切り替えでWebView2を頻繁に生成・破棄する場合は、ユーザーデータフォルダーや初期化タイミングにも注意が必要です。表示されない、真っ白になる、初期化が遅いといった問題は、レイアウトではなく初期化順序が原因のこともあります。
4-6. 最小構成のサンプルコード
WPFの最小構成は次の通りです。
XML<Window x:Class="WpfWebView2Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
Title="WebView2 Sample"
Width="1000"
Height="700">
<Grid>
<wv2:WebView2 x:Name="WebView" />
</Grid>
</Window>
C#using System.Windows;
namespace WpfWebView2Sample;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
await WebView.EnsureCoreWebView2Async();
WebView.CoreWebView2.Navigate("https://example.com");
}
}
5. WebView2の基本操作
WebView2を実務で使う場合、単にページを表示するだけでなく、戻る・進む、URL取得、ページ読み込み完了、JavaScript実行、C#との連携などが必要になります。ここでは基本操作をまとめます。
5-1. 戻る・進む・再読み込みを実装する
戻る・進むはCanGoBack、CanGoForwardで判定し、GoBack、GoForwardを呼び出します。
C#if (webView.CoreWebView2.CanGoBack)
{
webView.CoreWebView2.GoBack();
}
if (webView.CoreWebView2.CanGoForward)
{
webView.CoreWebView2.GoForward();
}
再読み込みはReloadです。
C#webView.CoreWebView2.Reload();
簡易ブラウザを作る場合は、戻るボタン、進むボタン、再読み込みボタンを用意し、ナビゲーション完了時にボタンの有効・無効を更新すると使いやすくなります。
5-2. 現在のURLやタイトルを取得する
現在のURLはSourceまたはCoreWebView2.Sourceから取得できます。
C#string currentUrl = webView.Source?.ToString() ?? "";
ページタイトルはCoreWebView2.DocumentTitleで取得できます。
C#string title = webView.CoreWebView2.DocumentTitle;
タイトルバーに現在のページタイトルを表示する例です。
C#webView.CoreWebView2.DocumentTitleChanged += (_, _) =>
{
Text = webView.CoreWebView2.DocumentTitle;
};
5-3. ページ読み込み完了を検知する
ページ読み込み完了はNavigationCompletedイベントで検知できます。
C#webView.CoreWebView2.NavigationCompleted += (_, e) =>
{
if (e.IsSuccess)
{
MessageBox.Show("読み込みが完了しました。");
}
else
{
MessageBox.Show($"読み込みに失敗しました: {e.WebErrorStatus}");
}
};
読み込み完了後にJavaScriptを実行したい場合は、このイベント内でExecuteScriptAsyncを呼ぶと実装しやすくなります。
5-4. JavaScriptを実行する
C#側からJavaScriptを実行するには、ExecuteScriptAsyncを使います。MicrosoftのAPIリファレンスでは、ExecuteScriptAsyncは現在のトップレベルドキュメントでJavaScriptコードを実行し、結果をJSONエンコードされた文字列として返すと説明されています。
C#string result = await webView.CoreWebView2.ExecuteScriptAsync(
"document.title"
);
MessageBox.Show(result);
戻り値はJSON形式です。たとえば文字列の結果は"title"のようにダブルクォート付きで返るため、必要に応じてJSONとしてデコードします。
C#using System.Text.Json;
string json = await webView.CoreWebView2.ExecuteScriptAsync("document.title");
string? title = JsonSerializer.Deserialize<string>(json);
5-5. JavaScriptからC#へ値を渡す
JavaScript側からC#へ値を渡すには、window.chrome.webview.postMessageを使います。C#側ではWebMessageReceivedイベントを購読します。WebMessageReceivedは、WebViewのトップレベルドキュメントがwindow.chrome.webview.postMessageを実行したときに発生します。
C#側のコードです。
C#webView.CoreWebView2.WebMessageReceived += (_, e) =>
{
string message = e.TryGetWebMessageAsString();
MessageBox.Show($"JavaScriptから受信: {message}");
};
HTML側のコードです。
HTML<button onclick="sendMessage()">送信</button>
<script>
function sendMessage() {
window.chrome.webview.postMessage("Hello from JavaScript");
}
</script>
JSONを渡す場合は、C#側でWebMessageAsJsonを取得してデシリアライズすると扱いやすくなります。
5-6. C#からJavaScriptへ値を渡す
C#からJavaScriptへ値を渡す方法はいくつかあります。単純な値ならExecuteScriptAsyncで関数を呼び出せます。
C#string name = "Taro";
string jsonName = JsonSerializer.Serialize(name);
await webView.CoreWebView2.ExecuteScriptAsync(
$"setUserName({jsonName});"
);
JavaScript側です。
HTML<script>
function setUserName(name) {
document.getElementById("userName").textContent = name;
}
</script>
<div id="userName"></div>
文字列を直接連結すると、クォートや改行、特殊文字でJavaScriptが壊れたり、インジェクションの原因になったりします。値は必ずJSONとしてエンコードしてから渡すのが安全です。
5-7. 新しいウィンドウの制御
Webページ内でtarget="_blank"やwindow.openが使われると、新しいウィンドウを開こうとすることがあります。アプリ内で同じWebViewに表示したい場合は、NewWindowRequestedイベントで制御します。
C#webView.CoreWebView2.NewWindowRequested += (_, e) =>
{
e.Handled = true;
webView.CoreWebView2.Navigate(e.Uri);
};
外部ブラウザーで開きたい場合は、Process.Startを使います。
C#using System.Diagnostics;
webView.CoreWebView2.NewWindowRequested += (_, e) =>
{
e.Handled = true;
Process.Start(new ProcessStartInfo
{
FileName = e.Uri,
UseShellExecute = true
});
};
業務アプリでは、ログイン画面や外部リンクをどこで開くかを明確に決めておくことが重要です。
5-8. DevToolsを有効・無効にする
WebView2では、開発者ツールを開けるかどうかをAreDevToolsEnabledで制御できます。このプロパティは、ユーザーがコンテキストメニューやキーボードショートカットからDevToolsを開けるかを決めるもので、既定値はtrueです。
本番環境でDevToolsを無効にしたい場合は、初期化後に次のように設定します。
C#webView.CoreWebView2.Settings.AreDevToolsEnabled = false;
ただし、開発中はDevToolsが非常に役立ちます。HTML、CSS、JavaScript、ネットワーク通信、コンソールエラーを確認できるため、デバッグ時は有効にしておくのがおすすめです。
6. C# WebViewでローカルファイル・社内ページを表示する方法
WebView2は外部サイトだけでなく、ローカルHTML、アプリ内リソース、localhostで動作するWebアプリ、社内サイトの表示にも使えます。ここではよくある表示パターンを解説します。
6-1. ローカルHTMLファイルを表示する
ローカルHTMLファイルを表示するには、ファイルパスをUriに変換して指定します。
C#string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "help", "index.html");
webView.Source = new Uri(path);
または、NavigateにファイルURIを渡します。
C#string fileUri = new Uri(path).AbsoluteUri;
webView.CoreWebView2.Navigate(fileUri);
ただし、ローカルファイルを直接表示する場合、CSS、JavaScript、画像の相対パスやセキュリティ制約に注意が必要です。複数ファイルで構成されたHTMLを扱う場合は、後述する仮想ホスト名マッピングが便利です。
6-2. アプリ内リソースのHTMLを表示する
アプリに埋め込んだHTMLテンプレートや、C#側で生成したHTMLを表示する場合は、NavigateToStringを使います。
C#string html = GenerateHtmlReport();
webView.NavigateToString(html);
帳票プレビュー、ログビューア、Markdown変換結果、メールテンプレート確認などに向いています。
ただし、NavigateToStringで表示するHTMLから外部CSSや画像を読み込む場合、パス解決に注意が必要です。画像やCSSを安定して読み込みたい場合は、HTMLファイルとして配置するか、仮想ホスト名マッピングを使うとよいでしょう。
6-3. CSS・JavaScript・画像ファイルを読み込む
ローカルHTMLが次のような構成になっているとします。
assets/
index.html
css/site.css
js/app.js
images/logo.png
この場合、index.htmlをファイルURIで開けば、相対パスでCSSや画像を読み込めることがあります。
HTML<link rel="stylesheet" href="css/site.css">
<script src="js/app.js"></script>
<img src="images/logo.png">
ただし、file://での読み込みは環境やセキュリティ設定によって扱いづらい場合があります。業務アプリで安定して配布したい場合は、ローカルフォルダーを仮想的なHTTPSホストに割り当てる方法を検討します。
6-4. 仮想ホスト名マッピングを使う
WebView2には、ローカルフォルダーを仮想ホスト名に割り当てるSetVirtualHostNameToFolderMappingがあります。このメソッドは、仮想ホスト名とフォルダーパスのマッピングを設定し、そのホスト名経由でWebサイトからローカルフォルダーを利用できるようにします。
C#using Microsoft.Web.WebView2.Core;
await webView.EnsureCoreWebView2Async();
string assetsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assets");
webView.CoreWebView2.SetVirtualHostNameToFolderMapping(
"appassets.example",
assetsPath,
CoreWebView2HostResourceAccessKind.DenyCors
);
webView.CoreWebView2.Navigate("https://appassets.example/index.html");
これにより、HTML内では次のように相対パスを使えます。
HTML<link rel="stylesheet" href="/css/site.css">
<script src="/js/app.js"></script>
<img src="/images/logo.png">
file://よりWebアプリに近い構成で扱えるため、ローカルHTMLを本格的に表示する場合に便利です。
6-5. localhostのWebアプリを表示する
ASP.NET Core、Blazor、React、Vueなどで作ったWebアプリをローカルサーバーとして起動し、WebView2で表示する方法もあります。
C#webView.CoreWebView2.Navigate("http://localhost:5000");
この構成は、既存のWebアプリをデスクトップアプリのように見せたい場合に便利です。C#側でローカルWebサーバーを起動し、WebView2でその画面を表示すれば、HTML/CSS/JavaScriptで作ったUIをデスクトップアプリとして配布できます。
注意点として、ポート競合、起動順序、ローカルサーバーの終了処理、ファイアウォール、認証情報の扱いを設計しておく必要があります。
6-6. 社内サイトや認証付きページを表示する際の注意点
社内サイトや認証付きページをWebView2で表示する場合は、認証方式、Cookie、プロキシ、証明書、シングルサインオンの挙動を確認しましょう。
たとえば、社内プロキシを通る必要がある環境、クライアント証明書が必要な環境、統合Windows認証を使う環境では、通常のブラウザーと同じように見えても、WebView2内では追加設定や検証が必要になることがあります。
また、社内システムをアプリ内に表示する場合でも、外部リンクへ遷移できる状態はリスクになります。表示してよいURLをホワイトリスト化し、想定外のドメインへの遷移をブロックする実装を入れることをおすすめします。
7. WebView2のエラー対処とトラブルシューティング
WebView2でよくあるトラブルは、「表示されない」「真っ白になる」「CoreWebView2がnull」「Runtimeがない」「JavaScriptが動かない」などです。原因を切り分けるには、初期化、Runtime、URL、ネットワーク、セキュリティ、イベントログを順番に確認します。
7-1. WebView2が表示されない原因
WebView2が表示されない場合、まず次の点を確認します。
NuGetパッケージがインストールされているか、WebView2 Runtimeが実行環境にあるか、WebView2コントロールのサイズが0になっていないか、DockやWPFのレイアウト設定が正しいか、初期化前に操作していないか、表示対象URLにアクセスできるかを確認します。
特に配布先PCでだけ表示されない場合は、WebView2 Runtime未インストールの可能性があります。WebView2アプリ配布時はクライアントPCにRuntimeが存在することを確認する必要があります。
7-2. CoreWebView2がnullになる原因と対処
CoreWebView2がnullになる主な原因は、初期化が完了する前にアクセスしていることです。
悪い例です。
C#webView.CoreWebView2.Navigate("https://example.com");
初期化前のため、CoreWebView2がnullの可能性があります。
正しい例です。
C#await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.Navigate("https://example.com");
イベント登録も初期化後に行います。
C#await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigationCompleted += (_, e) =>
{
// 読み込み完了処理
};
7-3. 初期化エラーが発生する原因と対処
初期化エラーが発生する場合、WebView2 Runtimeが存在しない、ユーザーデータフォルダーにアクセスできない、固定バージョンRuntimeのパスが間違っている、アプリの実行権限が不足している、32bit・64bitの構成が合っていない、といった原因が考えられます。
ユーザーデータフォルダーを明示的に指定する例です。
C#string userDataFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"MyApp",
"WebView2"
);
var environment = await CoreWebView2Environment.CreateAsync(
browserExecutableFolder: null,
userDataFolder: userDataFolder
);
await webView.EnsureCoreWebView2Async(environment);
業務アプリでは、Program Files配下のような書き込み権限が制限される場所をユーザーデータフォルダーにしないよう注意します。
7-4. WebView2 Runtimeが未インストールの場合の対処
Runtimeが未インストールの場合は、インストーラーでWebView2 Runtimeを導入するか、アプリ起動時に案内します。
Microsoftの配布ドキュメントでは、オンライン環境向けには小さなEvergreen Bootstrapper、オフライン環境向けにはEvergreen Standalone Installerが用意されていると説明されています。Bootstrapperはユーザーのデバイスアーキテクチャに一致するRuntimeをMicrosoftサーバーからダウンロードしてインストールし、Standalone Installerはオフライン環境にRuntimeをインストールする完全なインストーラーです。
アプリ側では、起動時に次のように検出できます。
C#string? version = CoreWebView2Environment.GetAvailableBrowserVersionString();
if (string.IsNullOrEmpty(version))
{
MessageBox.Show(
"このアプリを実行するにはWebView2 Runtimeが必要です。インストーラーを実行してください。"
);
return;
}
7-5. ページが真っ白になる場合の確認ポイント
ページが真っ白になる場合は、次の順に確認します。
まず、URLにブラウザーからアクセスできるか確認します。次に、WebView2のNavigationCompletedでエラーが出ていないか確認します。さらに、DevToolsを開いてConsoleとNetworkを確認します。
C#webView.CoreWebView2.NavigationCompleted += (_, e) =>
{
if (!e.IsSuccess)
{
MessageBox.Show($"読み込み失敗: {e.WebErrorStatus}");
}
};
ローカルHTMLの場合は、CSSやJavaScriptの相対パスが間違っていることもあります。NavigateToStringで表示したHTMLから外部ファイルを読み込む場合は、基準URLが想定と異なるため、仮想ホスト名マッピングやローカルファイル表示に切り替えると解決しやすくなります。
7-6. JavaScriptが実行されない場合の対処
JavaScriptが実行されない場合は、CoreWebView2の初期化後に実行しているか、ページ読み込み完了後に実行しているか、IsScriptEnabledがfalseになっていないかを確認します。
C#webView.CoreWebView2.Settings.IsScriptEnabled = true;
ExecuteScriptAsyncの戻り値が"null"になる場合は、JavaScript側で例外が発生している、戻り値がundefined、JSONに変換できない値を返している、といった原因が考えられます。ExecuteScriptAsyncは結果をJSONエンコードされた文字列として返し、undefinedやJSON化できない結果はnullとして返ることがあります。
7-7. SSL証明書エラーの対処
社内サイトや開発環境のHTTPSページを表示すると、証明書エラーが原因でページが表示されないことがあります。原則として、本番環境では正しい証明書を設定するべきです。
開発環境で一時的に証明書エラーを許可する場合は、対象ホストを限定して処理します。すべての証明書エラーを無条件に許可する実装は危険です。
C#webView.CoreWebView2.ServerCertificateErrorDetected += (_, e) =>
{
if (e.RequestUri.StartsWith("https://dev.example.local"))
{
e.Action = CoreWebView2ServerCertificateErrorAction.AlwaysAllow;
}
else
{
e.Action = CoreWebView2ServerCertificateErrorAction.Cancel;
}
};
本番では、信頼された証明機関から発行された証明書を使い、期限切れやホスト名不一致を解消してください。
7-8. 32bit・64bitの違いによるエラー対処
WebView2アプリでは、アプリ本体のプラットフォームターゲットとRuntime、ネイティブローダーの構成を確認する必要があります。Microsoftの配布ドキュメントでは、配布物にwin-arm64、win-x64、win-x86向けのWebView2Loader.dllが含まれる構成が示されています。
通常はNuGetパッケージが必要なファイルを処理しますが、単一ファイル配布、独自インストーラー、固定バージョンRuntimeを使う場合は、対象CPUに合った構成になっているか確認しましょう。
迷った場合は、まずAny CPUではなくx64など配布対象に合わせて明示し、動作確認を行うと原因を切り分けやすくなります。
7-9. デバッグ時に確認すべきログとイベント
WebView2のデバッグでは、次のイベントを確認すると原因を追いやすくなります。
CoreWebView2InitializationCompleted、NavigationStarting、ContentLoading、NavigationCompleted、WebResourceRequested、ProcessFailed、NewWindowRequested、WebMessageReceivedです。
例です。
C#webView.CoreWebView2InitializationCompleted += (_, e) =>
{
Debug.WriteLine($"Initialization: {e.IsSuccess}");
};
webView.NavigationStarting += (_, e) =>
{
Debug.WriteLine($"Starting: {e.Uri}");
};
webView.NavigationCompleted += (_, e) =>
{
Debug.WriteLine($"Completed: {e.IsSuccess}, {e.WebErrorStatus}");
};
webView.CoreWebView2.ProcessFailed += (_, e) =>
{
Debug.WriteLine($"Process failed: {e.ProcessFailedKind}");
};
また、開発中はDevToolsを開き、Consoleエラー、Networkの失敗、CORS、証明書、JavaScript例外を確認します。
8. WebView2アプリの配布方法
WebView2アプリを配布するときは、アプリ本体だけでなく、WebView2 Runtimeをどう扱うかを決める必要があります。ここを設計していないと、開発PCでは動くのにユーザーPCで起動しないという問題が起きます。
8-1. WebView2 Runtimeを含めるべきか判断する
まず、配布先PCにWebView2 Runtimeがある前提でよいかを決めます。Windows 11ではEvergreen WebView2 RuntimeがOSの一部として含まれると説明されていますが、一部のデバイスではRuntimeが事前インストールされていない可能性があるため、存在確認が推奨されています。
社内PCを管理していてRuntimeを事前配布できるなら、アプリ本体に含めない構成でも運用できます。一方、一般ユーザー向けやオフライン環境向けでは、インストーラーにRuntime導入処理を含めるほうが安全です。
8-2. Evergreen Bootstrapperで配布する方法
Evergreen Bootstrapperは、小さなインストーラーを使って、実行時に必要なRuntimeをダウンロードしてインストールする方式です。オンライン環境での配布に向いています。
サイレントインストール例です。
batMicrosoftEdgeWebView2Setup.exe /silent /install
Microsoftの配布ドキュメントでは、Bootstrapperは約2MBの小さなインストーラーで、ユーザーのデバイスアーキテクチャに一致するEvergreen RuntimeをMicrosoftサーバーからダウンロードしてインストールすると説明されています。
8-3. Evergreen Standalone Installerで配布する方法
Evergreen Standalone Installerは、Runtime本体を含む完全なインストーラーです。オフライン環境や、インストール時にインターネット接続を期待できない環境に向いています。
サイレントインストール例です。
batMicrosoftEdgeWebView2RuntimeInstallerX64.exe /silent /install
Microsoftの配布ドキュメントでも、完全にオフラインで動作する展開シナリオではEvergreen Standalone Installerをアプリのインストーラーやアップデーターに含め、Runtimeが未インストールの場合に実行する流れが説明されています。
8-4. 固定バージョンRuntimeで配布する方法
固定バージョンRuntimeを使う場合は、特定バージョンのWebView2 Runtimeをアプリと一緒に配布します。
基本的な流れは、固定バージョンRuntimeをダウンロードし、展開し、アプリの配布物に含め、CoreWebView2Environment.CreateAsyncでbrowserExecutableFolderを指定する形です。Microsoftの配布ドキュメントでも、固定バージョンRuntimeではバイナリをアプリパッケージに含め、WebView2環境作成時に固定バージョンバイナリへのパスを指定すると説明されています。
C#string runtimePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"FixedRuntime"
);
var environment = await CoreWebView2Environment.CreateAsync(
browserExecutableFolder: runtimePath,
userDataFolder: null
);
await webView.EnsureCoreWebView2Async(environment);
固定バージョン方式は、検証済みのRuntimeだけを使いたい場合に有効ですが、セキュリティ更新を自分たちで管理する必要があります。
8-5. ClickOnce・MSIX・インストーラー配布時の注意点
ClickOnce、MSIX、WiX、Inno Setup、独自インストーラーなど、どの配布方式でも共通して重要なのは、Runtimeの存在確認とインストール手順です。
MSIXでは依存関係としてWebView2 Runtimeを指定する方法があります。Microsoftの配布ドキュメントでも、MSIXアプリケーションをデプロイする場合はWebView2 Runtimeを依存関係として指定し、アプリケーションと共にインストールできると説明されています。
ClickOnceや独自インストーラーでは、アプリ起動前またはインストール時にRuntimeを確認し、未インストールならBootstrapperまたはStandalone Installerを実行する構成にします。
8-6. オフライン環境へ配布する場合の注意点
オフライン環境では、BootstrapperはRuntimeをダウンロードできないため使えません。Evergreen Standalone Installerを同梱するか、固定バージョンRuntimeをアプリに含める必要があります。
また、オフライン環境ではRuntimeの自動更新が期待できないため、セキュリティ更新の運用を決めておく必要があります。Microsoftの配布ドキュメントでは、Evergreen Runtimeの新しいバージョンは自動的にダウンロードされ、アプリ再起動時に新しいRuntimeが使われる一方、継続実行中のアプリは以前のRuntimeを使い続けるため、脅威モデルに応じて最新Runtimeを早く採用すべきか検討する必要があると説明されています。
9. WebView2を安全に使うための設定
WebView2は便利ですが、Webコンテンツをネイティブアプリ内で動かすため、セキュリティ設計を間違えるとリスクになります。特に外部サイト表示、JavaScript連携、ローカルファイルアクセス、認証情報の扱いには注意が必要です。
9-1. 外部サイトを表示する場合のセキュリティリスク
外部サイトを表示する場合、表示しているWebコンテンツを完全に信頼しない設計が必要です。Microsoftのセキュリティガイドでも、WebView2内で実行されているドキュメントの配信元を常に確認し、ExecuteScriptやPostWebMessageAsJson、PostWebMessageAsStringなどで情報を送る前にコンテンツの信頼性を評価するよう説明されています。
特に、WebページからC#側の処理を呼び出す設計では、悪意あるページへ遷移した場合に不正なメッセージを送られる可能性があります。表示中のURLを確認し、許可したドメイン以外では連携処理を無効化することが重要です。
9-2. 許可するURLを制限する
想定外のページへ遷移させないために、NavigationStartingでURLをチェックします。
C#webView.CoreWebView2.NavigationStarting += (_, e) =>
{
var uri = new Uri(e.Uri);
bool allowed =
uri.Host == "example.com" ||
uri.Host.EndsWith(".example.com");
if (!allowed)
{
e.Cancel = true;
MessageBox.Show("許可されていないURLへの移動をブロックしました。");
}
};
WebView2のセキュリティガイドでも、特定のページに移動しないようにするにはNavigationStartingやFrameNavigationStartingでページやフレームのナビゲーションをチェックし、条件付きでブロックすると説明されています。
9-3. ファイルアクセスを制御する
ローカルファイルを表示する場合、Webコンテンツに不要なファイルアクセスを許可しないことが重要です。仮想ホスト名マッピングを使う場合も、公開するフォルダーを必要最小限に限定します。
悪い例は、アプリのルートフォルダーやユーザーのドキュメントフォルダー全体を公開することです。良い例は、assetsやhelpなど、WebView2から読み込ませたい静的ファイルだけを置いた専用フォルダーを公開することです。
C#webView.CoreWebView2.SetVirtualHostNameToFolderMapping(
"appassets.example",
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assets"),
CoreWebView2HostResourceAccessKind.DenyCors
);
SetVirtualHostNameToFolderMappingでは、仮想ホスト名、マッピングするフォルダーパス、他サイトからのリソースアクセスレベルを指定できます。
9-4. JavaScript連携時の入力チェック
JavaScriptからC#へ渡される値は、必ず検証します。
C#webView.CoreWebView2.WebMessageReceived += (_, e) =>
{
string json = e.WebMessageAsJson;
try
{
var request = JsonSerializer.Deserialize<AppRequest>(json);
if (request is null || string.IsNullOrWhiteSpace(request.Command))
{
return;
}
if (request.Command == "open-report")
{
OpenReport(request.ReportId);
}
}
catch (JsonException)
{
// 不正なJSONは無視またはログ出力
}
};
Microsoftのセキュリティガイドでも、Webメッセージやホストオブジェクトのパラメーターは、形式不正または悪意ある可能性があるため、使用前に検証するよう説明されています。
9-5. 開発者ツールやコンテキストメニューを制御する
本番環境では、必要に応じてDevToolsや標準コンテキストメニューを無効にします。
C#webView.CoreWebView2.Settings.AreDevToolsEnabled = false;
webView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
AreDevToolsEnabledは、ユーザーがコンテキストメニューやキーボードショートカットでDevToolsを開けるかを制御します。既定値はtrueです。
ただし、DevToolsを無効にしてもセキュリティ対策の代わりにはなりません。URL制限、メッセージ検証、認証情報の保護を優先しましょう。
9-6. Cookie・キャッシュ・ユーザーデータの扱い
WebView2はCookie、キャッシュ、ローカルストレージなどのユーザーデータを持ちます。業務アプリでは、ログイン情報やセッション情報が残ることを前提に設計する必要があります。
ユーザーデータフォルダーをアプリごとに分けたい場合は、CoreWebView2Environment.CreateAsyncでuserDataFolderを指定します。
C#string userDataFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"MyCompany",
"MyApp",
"WebView2UserData"
);
var environment = await CoreWebView2Environment.CreateAsync(
userDataFolder: userDataFolder
);
await webView.EnsureCoreWebView2Async(environment);
共有PCやログアウト機能があるアプリでは、Cookie削除やユーザーデータのクリアも検討します。認証付きページを表示する場合は、アプリ終了時にどこまで情報を残すかを要件として決めておきましょう。
10. C# WebView2の実装サンプル集
ここでは、実務でよく使うWebView2の実装例を紹介します。必要な部分だけ組み合わせて使えます。
10-1. URL入力付き簡易ブラウザを作る
WinFormsで簡易ブラウザを作る例です。
C#using Microsoft.Web.WebView2.WinForms;
public class BrowserForm : Form
{
private readonly TextBox addressBar = new() { Dock = DockStyle.Top };
private readonly WebView2 webView = new() { Dock = DockStyle.Fill };
public BrowserForm()
{
Text = "簡易ブラウザ";
Width = 1000;
Height = 700;
addressBar.KeyDown += AddressBar_KeyDown;
Controls.Add(webView);
Controls.Add(addressBar);
Load += async (_, _) =>
{
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.Navigate("https://example.com");
};
}
private void AddressBar_KeyDown(object? sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Enter || webView.CoreWebView2 is null)
{
return;
}
string url = addressBar.Text.Trim();
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
{
url = "https://" + url;
}
webView.CoreWebView2.Navigate(url);
}
}
10-2. HTMLビューアを作る
C#で生成したHTMLを表示するビューアです。
C#private void ShowHtmlPreview(string title, string body)
{
string html = $"""
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{System.Net.WebUtility.HtmlEncode(title)}</title>
<style>
body {{ font-family: sans-serif; padding: 24px; }}
.card {{ border: 1px solid #ddd; padding: 16px; border-radius: 8px; }}
</style>
</head>
<body>
<div class="card">
<h1>{System.Net.WebUtility.HtmlEncode(title)}</h1>
<p>{System.Net.WebUtility.HtmlEncode(body)}</p>
</div>
</body>
</html>
""";
webView.NavigateToString(html);
}
ユーザー入力をHTMLに埋め込む場合は、必ずHTMLエンコードします。
10-3. ログインページをアプリ内に表示する
ログインページをWebView2で表示し、ログイン完了URLを検知する例です。
C#await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigationStarting += (_, e) =>
{
if (e.Uri.StartsWith("https://app.example.com/login-complete"))
{
e.Cancel = true;
MessageBox.Show("ログインが完了しました。");
}
};
webView.CoreWebView2.Navigate("https://app.example.com/login");
OAuthや外部IDプロバイダーを使う場合は、組み込みWebViewでのログインが許可されているか、リダイレクトURIやセキュリティ要件を事前に確認してください。
10-4. JavaScriptとC#を連携する
C#とJavaScriptで双方向に通信する例です。
C#側です。
C#await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.WebMessageReceived += async (_, e) =>
{
string message = e.TryGetWebMessageAsString();
if (message == "get-time")
{
string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string json = JsonSerializer.Serialize(now);
await webView.CoreWebView2.ExecuteScriptAsync(
$"window.setTime({json});"
);
}
};
webView.NavigateToString("""
<!doctype html>
<html>
<body>
<button onclick="requestTime()">現在時刻を取得</button>
<div id="result"></div>
<script>
function requestTime() {
window.chrome.webview.postMessage("get-time");
}
function setTime(value) {
document.getElementById("result").textContent = value;
}
</script>
</body>
</html>
""");
JavaScriptからC#へはpostMessage、C#からJavaScriptへはExecuteScriptAsyncを使います。ExecuteScriptAsyncは現在のドキュメントでJavaScriptを実行し、結果をJSONエンコードされた文字列として返します。
10-5. PDFや画像を表示する
WebView2では、PDFや画像ファイルを表示することもできます。ローカルPDFを表示する例です。
C#string pdfPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sample.pdf");
webView.Source = new Uri(pdfPath);
画像をHTMLとして表示する例です。
C#string imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "images", "sample.png");
string imageUri = new Uri(imagePath).AbsoluteUri;
webView.NavigateToString($"""
<!doctype html>
<html>
<body style="margin:0;">
<img src="{imageUri}" style="max-width:100%; height:auto;">
</body>
</html>
""");
複数の画像やCSSを使うビューアを作る場合は、仮想ホスト名マッピングを使うとパス管理が楽になります。
10-6. 業務アプリにWeb画面を埋め込む
業務アプリでよくある構成は、左側にC#ネイティブのメニュー、右側にWebView2を配置し、選択したメニューに応じて社内Web画面を表示する形です。
C#private void OpenCustomerPage(string customerId)
{
string encodedId = Uri.EscapeDataString(customerId);
string url = $"https://intranet.example.com/customers/{encodedId}";
webView.CoreWebView2.Navigate(url);
}
この場合、顧客IDや伝票番号などをURLに含める前に必ずエンコードします。また、WebView2側で表示できるドメインを社内サイトに限定し、外部リンクは標準ブラウザーで開くなど、遷移ルールを決めておくと安全です。
11. C# WebView2でよくある質問
ここでは、C# WebView2を導入するときによくある疑問に回答します。
11-1. WebView2はEdgeがインストールされていないと使えない?
WebView2アプリの運用環境では、Microsoft Edgeブラウザーそのものではなく、WebView2 Runtimeを使う前提で考えます。Microsoftの配布ドキュメントでは、WebView2アプリの運用リリースではMicrosoft EdgeではなくWebView2 RuntimeのみをバッキングWebプラットフォームとして使用できると説明されています。
つまり、「Edgeブラウザーがあるか」ではなく、「WebView2 Runtimeがあるか」を確認することが重要です。
11-2. WebView2 RuntimeはユーザーPCに必要?
必要です。WebView2アプリを配布するときは、クライアントPCにWebView2 Runtimeが存在することを確認する必要があります。
Runtimeがない環境では、Evergreen Bootstrapper、Evergreen Standalone Installer、固定バージョンRuntimeのいずれかで対応します。
11-3. WebBrowserコントロールから移行できる?
多くの場合、移行できます。ただし、WebBrowserとWebView2ではAPIやイベント、JavaScript連携の方法が異なります。
単純にURLを表示するだけなら移行は比較的簡単です。一方、Documentオブジェクトを直接操作している場合、IE固有の挙動に依存している場合、ActiveXや古いHTMLを使っている場合は、実装を見直す必要があります。
移行時は、まず表示だけWebView2へ置き換え、その後にJavaScript連携やイベント処理を段階的に移すのがおすすめです。
11-4. WinFormsとWPFではどちらが簡単?
既存のWinFormsアプリに追加するだけならWinFormsのほうが簡単です。フォームにWebView2を置いてDockStyle.Fillを設定すれば、すぐに表示できます。
新規開発で、画面レイアウトやデザインを柔軟に作りたい場合はWPFが向いています。WPFではXAMLでレイアウトを管理できるため、ネイティブUIとWebView2を組み合わせた画面を作りやすくなります。
11-5. オフライン環境でも使える?
使えます。ただし、表示するコンテンツとRuntime配布方法をオフライン向けに設計する必要があります。
ローカルHTMLを表示するだけなら、HTML、CSS、JavaScript、画像をアプリに同梱すれば表示できます。Runtimeについては、BootstrapperではなくEvergreen Standalone Installerを同梱するか、固定バージョンRuntimeを配布します。Microsoftの配布ドキュメントでも、オフライン展開ではEvergreen Standalone Installerをアプリのインストーラーやアップデーターに含める流れが説明されています。
11-6. BlazorやASP.NETの画面を表示できる?
表示できます。ASP.NET CoreやBlazor Server、Blazor WebAssembly、React、Vueなどで作ったWebアプリをローカルまたは社内サーバーで動かし、そのURLをWebView2で表示できます。
ローカルでWebサーバーを起動する構成では、アプリ起動時にサーバーを開始し、WebView2でlocalhostを開き、アプリ終了時にサーバーを停止する設計が必要です。
11-7. 商用アプリで利用できる?
WebView2は商用アプリでも広く利用される技術です。ただし、配布時にはWebView2 Runtimeの配布方法、更新方法、ライセンス、企業内のソフトウェア配布ポリシーを確認してください。
特に企業向けアプリでは、Runtimeの自動更新を許可するか、固定バージョンで検証するか、WSUSなどで管理するかを事前に決めておくと運用しやすくなります。Microsoftの配布ドキュメントでも、WebView2 Runtimeの配布、Evergreen、固定バージョン、MSIX依存関係、オフライン配布などの選択肢が整理されています。
まとめ
C#でWebページやHTMLコンテンツを表示したい場合、現在はWebView2を使うのが基本です。WebView2はChromiumベースのMicrosoft Edgeをレンダリングエンジンとして利用し、WinForms、WPF、WinUIなどのC#デスクトップアプリにWebコンテンツを埋め込めます。
導入の流れは、Visual Studioでプロジェクトを作成し、Microsoft.Web.WebView2をNuGetでインストールし、WebView2コントロールを配置し、EnsureCoreWebView2Asyncで初期化してからURLやHTMLを表示する、という順番です。
WinFormsではDockStyle.Fillで簡単に画面全体へ配置できます。WPFではXAMLにwv2:WebView2を配置し、Gridなどでレイアウトを整えると扱いやすくなります。JavaScript連携では、C#からはExecuteScriptAsync、JavaScriptからC#へはwindow.chrome.webview.postMessageとWebMessageReceivedを使います。
実務で重要なのは、WebView2 Runtimeの配布とセキュリティです。配布先PCにRuntimeがあるかを確認し、必要に応じてEvergreen Bootstrapper、Evergreen Standalone Installer、固定バージョンRuntimeを選びます。また、外部サイト表示やJavaScript連携では、URL制限、入力チェック、ローカルファイルアクセス制御、DevToolsやコンテキストメニューの制御を行い、安全な設計にすることが大切です。

