如何在 C# 中將 WebView2 遷移到 IronPDF
WebView2 是微軟的嵌入式 Edge/Chromium 瀏覽器控制項,它為開發者提供了一種在 Windows 應用程式中顯示 Web 內容的方法。 然而,當開發團隊嘗試使用 WebView2 產生 PDF 時,他們會遇到嚴重的架構限制,使其不適合生產環境。 WebView2 是一個專為 UI 應用程式設計的瀏覽器嵌入控件,而不是 PDF 生成庫。
本指南提供了從 WebView2 到 IronPDF 的完整遷移路徑,包括逐步說明、程式碼比較和實用範例,適用於需要在應用程式中可靠產生 PDF 的專業 .NET 開發人員。
重要警告:WebView2 不適用於產生 PDF 文件
在研究遷移路徑之前,開發團隊必須了解為什麼 WebView2 在用於建立 PDF 時會產生重大問題:
| 問題 | 影響 | 嚴重程度 |
|---|---|---|
| 內存洩漏 | WebView2 在長時間運行的進程中存在有據可查的記憶體洩漏問題。 您的伺服器將會崩潰。 | 批判的 |
| 僅限 Windows | 對 Linux、macOS、Docker 或雲端環境完全不支持 | 批判的 |
| 需要 UI 執行緒 | 必須在帶有訊息循環的 STA 線程上運行。無法在 Web 伺服器或 API 中使用。 | 批判的 |
| 並非為PDF設計 | PrintToPdfAsync是事後新增的功能,並非核心功能。 | 高的 |
| 服務不穩定 | Windows 服務和後台工作進程中經常出現崩潰和掛起的情況。 | 高的 |
| 複雜非同步流 | 導航事件、完成回調、競態條件 | 高的 |
| 邊緣運行時依賴項 | 需要在目標電腦上安裝 Edge WebView2 執行階段。 | 中等的 |
| 無頭模式 | 即使隱藏,也始終建立 UI 元素 | 中等的 |
| 表現 | 啟動緩慢,資源消耗高 | 中等的 |
| 缺乏專業支持 | 微軟不支援 PDF 產生用例 | 中等的 |
現實世界中的故障場景
這些程式碼模式會導致生產環境故障:
// DANGER: This code WILL cause problems in production
// 問題 1: Memory leak - creates new WebView2 for each PDF
public async Task<byte[]> GeneratePdf(string html) // Called 1000x/day = server crash
{
using var webView = new WebView2(); // Memory not fully released!
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigateToString(html);
// ... memory accumulates until OOM
}
// 問題 2: UI thread requirement - crashes in ASP.NET
public IActionResult GenerateReport() // FAILS - no STA thread
{
var webView = new WebView2(); // InvalidOperationException
}
// 問題 3: Windows Service instability
public class PdfService : BackgroundService // Random crashes
{
protected override async Task ExecuteAsync(CancellationToken token)
{
// WebView2 + no message pump = hangs, crashes, undefined behavior
}
}// DANGER: This code WILL cause problems in production
// 問題 1: Memory leak - creates new WebView2 for each PDF
public async Task<byte[]> GeneratePdf(string html) // Called 1000x/day = server crash
{
using var webView = new WebView2(); // Memory not fully released!
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigateToString(html);
// ... memory accumulates until OOM
}
// 問題 2: UI thread requirement - crashes in ASP.NET
public IActionResult GenerateReport() // FAILS - no STA thread
{
var webView = new WebView2(); // InvalidOperationException
}
// 問題 3: Windows Service instability
public class PdfService : BackgroundService // Random crashes
{
protected override async Task ExecuteAsync(CancellationToken token)
{
// WebView2 + no message pump = hangs, crashes, undefined behavior
}
}IronPDF 與 WebView2:功能對比
了解架構差異有助於技術決策者評估遷移投資:
| 方面 | WebView2 | IronPDF |
|---|---|---|
| 目的 | 瀏覽器控制項(使用者介面) | PDF庫(專為PDF設計) |
| 生產就緒 | 不 | 是的 |
| 記憶體管理 | 長期運作中的洩漏 | 穩定,妥善處置 |
| 平台支援 | 僅限 Windows 系統 | Windows、Linux、macOS、Docker |
| 線程要求 | STA + 資訊泵 | 任何貼文 |
| 伺服器/雲 | 不支援 | 全力支持 |
| Azure/AWS/GCP | 有問題的 | 完美運行 |
| Docker | 不可能 | 官方圖片已發布 |
| ASP.NET Core | 無法工作 | 一流的支持 |
| 背景服務 | 不穩定 | 穩定的 |
| 支援的上下文 | 僅限 WinForms/WPF | 任何 .NET 環境:控制台、Web、桌面 |
| HTML 轉 PDF | 基本的 | 滿的 |
| PDF檔案的URL | 基本的 | 滿的 |
| 頁首/頁尾 | 不 | 是的(HTML) |
| 水印 | 不 | 是的 |
| 合併PDF | 不 | 是的 |
| 拆分PDF | 不 | 是的 |
| 數位簽名 | 不 | 是的 |
| 密碼保護 | 不 | 是的 |
| PDF/A 合規性 | 不 | 是的 |
| 專業支援 | PDF 版本無 | 是的 |
| 文件 | 有限的 | 廣泛的 |
快速入門:WebView2 到 IronPDF 的遷移
透過這些基礎步驟,遷移工作可以立即開始。
步驟 1:移除 WebView2 套件
dotnet remove package Microsoft.Web.WebView2dotnet remove package Microsoft.Web.WebView2或從項目文件中刪除:
<!-- REMOVE these packages -->
<PackageReference Include="Microsoft.Web.WebView2" Version="*" Remove /><!-- REMOVE these packages -->
<PackageReference Include="Microsoft.Web.WebView2" Version="*" Remove />步驟 2:安裝 IronPDF
dotnet add package IronPdfdotnet add package IronPdf步驟 3:更新命名空間
將 WebView2 命名空間替換為 IronPdf 命名空間:
// Before (WebView2)
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
// After (IronPDF)
using IronPdf;// Before (WebView2)
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
// After (IronPDF)
using IronPdf;步驟 4:初始化許可證
在應用程式啟動時新增許可證初始化:
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";程式碼遷移範例
將 HTML 轉換為 PDF
最基本的操作揭示了這些 .NET PDF 方法之間的複雜性差異。
WebView2 方法:
// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigateToString("<html><body><h1>Hello World</h1></body></html>");
await Task.Delay(2000);
await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
"{}"
);
}
}// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.NavigateToString("<html><body><h1>Hello World</h1></body></html>");
await Task.Delay(2000);
await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
"{}"
);
}
}IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Hello World</h1></body></html>");
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Hello World</h1></body></html>");
pdf.SaveAs("output.pdf");
}
}WebView2 版本需要使用EnsureCoreWebView2Async()進行非同步初始化,透過NavigateToString()進行導航,使用不可靠的Task.Delay(2000)等待渲染,以及與 DevTools 協定互動。 IronPDF 完全省去了這一步驟——創建渲染器,渲染 HTML,保存。
如需更進階的 HTML 轉 PDF 場景,請參閱HTML 轉 PDF 轉換指南。
將 URL 轉換為 PDF
URL 到 PDF 的轉換示範了 WebView2 複雜的非同步導航流程。
WebView2 方法:
// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
var tcs = new TaskCompletionSource<bool>();
webView.CoreWebView2.NavigationCompleted += (s, e) => tcs.SetResult(true);
webView.CoreWebView2.Navigate("https://example.com");
await tcs.Task;
await Task.Delay(1000);
var result = await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
"{\"printBackground\": true}"
);
var base64 = System.Text.Json.JsonDocument.Parse(result).RootElement.GetProperty("data").GetString();
File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64));
}
}// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
var tcs = new TaskCompletionSource<bool>();
webView.CoreWebView2.NavigationCompleted += (s, e) => tcs.SetResult(true);
webView.CoreWebView2.Navigate("https://example.com");
await tcs.Task;
await Task.Delay(1000);
var result = await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
"{\"printBackground\": true}"
);
var base64 = System.Text.Json.JsonDocument.Parse(result).RootElement.GetProperty("data").GetString();
File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64));
}
}IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("output.pdf");
}
}WebView2 需要建立TaskCompletionSource 、訂閱NavigationCompleted事件、呼叫CallDevToolsProtocolMethodAsync 、解析 JSON 回應以及解碼 base64 資料。 IronPDF 提供了一個專門的RenderUrlAsPdf方法,該方法在內部處理所有複雜性。
查看指向 PDF 文件的 URL ,以了解身份驗證和自訂標頭選項。
來自 HTML 文件的自訂 PDF 設定
配置頁面方向、頁邊距和紙張尺寸需要不同的方法。
WebView2 方法:
// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
string htmlFile = Path.Combine(Directory.GetCurrentDirectory(), "input.html");
webView.CoreWebView2.Navigate(htmlFile);
await Task.Delay(3000);
var printSettings = webView.CoreWebView2.Environment.CreatePrintSettings();
printSettings.Orientation = CoreWebView2PrintOrientation.Landscape;
printSettings.MarginTop = 0.5;
printSettings.MarginBottom = 0.5;
using (var stream = await webView.CoreWebView2.PrintToPdfAsync("custom.pdf", printSettings))
{
Console.WriteLine("Custom PDF created");
}
}
}// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
string htmlFile = Path.Combine(Directory.GetCurrentDirectory(), "input.html");
webView.CoreWebView2.Navigate(htmlFile);
await Task.Delay(3000);
var printSettings = webView.CoreWebView2.Environment.CreatePrintSettings();
printSettings.Orientation = CoreWebView2PrintOrientation.Landscape;
printSettings.MarginTop = 0.5;
printSettings.MarginBottom = 0.5;
using (var stream = await webView.CoreWebView2.PrintToPdfAsync("custom.pdf", printSettings))
{
Console.WriteLine("Custom PDF created");
}
}
}IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
string htmlFile = Path.Combine(Directory.GetCurrentDirectory(), "input.html");
var pdf = renderer.RenderHtmlFileAsPdf(htmlFile);
pdf.SaveAs("custom.pdf");
Console.WriteLine("Custom PDF created");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
using System.IO;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
string htmlFile = Path.Combine(Directory.GetCurrentDirectory(), "input.html");
var pdf = renderer.RenderHtmlFileAsPdf(htmlFile);
pdf.SaveAs("custom.pdf");
Console.WriteLine("Custom PDF created");
}
}WebView2 需要 3 秒的Task.Delay (一個不可靠的猜測),透過環境建立列印設置,並使用串流來呼叫PrintToPdfAsync 。 IronPDF 提供名稱清晰的直接RenderingOptions屬性,並使用毫米進行更精確的測量。
使用 DevTools 協定的高級 PDF 選項
複雜的 WebView2 配置需要 DevTools 協定互動。
WebView2 方法:
// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
var htmlPath = Path.GetFullPath("document.html");
var tcs = new TaskCompletionSource<bool>();
webView.CoreWebView2.NavigationCompleted += (s, e) => tcs.SetResult(true);
webView.CoreWebView2.Navigate($"file:///{htmlPath}");
await tcs.Task;
await Task.Delay(1000);
var options = new
{
landscape = false,
printBackground = true,
paperWidth = 8.5,
paperHeight = 11,
marginTop = 0.4,
marginBottom = 0.4,
marginLeft = 0.4,
marginRight = 0.4
};
var result = await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
JsonSerializer.Serialize(options)
);
var base64 = JsonDocument.Parse(result).RootElement.GetProperty("data").GetString();
File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64));
}
}// NuGet: Install-Package Microsoft.Web.WebView2.WinForms
using System;
using System.IO;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
class Program
{
static async Task Main()
{
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
var htmlPath = Path.GetFullPath("document.html");
var tcs = new TaskCompletionSource<bool>();
webView.CoreWebView2.NavigationCompleted += (s, e) => tcs.SetResult(true);
webView.CoreWebView2.Navigate($"file:///{htmlPath}");
await tcs.Task;
await Task.Delay(1000);
var options = new
{
landscape = false,
printBackground = true,
paperWidth = 8.5,
paperHeight = 11,
marginTop = 0.4,
marginBottom = 0.4,
marginLeft = 0.4,
marginRight = 0.4
};
var result = await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
"Page.printToPDF",
JsonSerializer.Serialize(options)
);
var base64 = JsonDocument.Parse(result).RootElement.GetProperty("data").GetString();
File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64));
}
}IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 40;
renderer.RenderingOptions.MarginBottom = 40;
renderer.RenderingOptions.MarginLeft = 40;
renderer.RenderingOptions.MarginRight = 40;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
var pdf = renderer.RenderHtmlFileAsPdf("document.html");
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 40;
renderer.RenderingOptions.MarginBottom = 40;
renderer.RenderingOptions.MarginLeft = 40;
renderer.RenderingOptions.MarginRight = 40;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
var pdf = renderer.RenderHtmlFileAsPdf("document.html");
pdf.SaveAs("output.pdf");
}
}WebView2 需要建構匿名物件、序列化為 JSON、呼叫 DevTools 協定方法、解析 JSON 回應以及手動解碼 base64。 IronPDF 提供具有清晰名稱和枚舉值的類型化屬性,例如PdfPaperSize.Letter 。
WebView2 API 到 IronPDF 映射參考
此映射透過顯示直接的 API 等效項來加速遷移:
| WebView2 API | IronPDF當量 | 筆記 |
|---|---|---|
new WebView2() | new ChromePdfRenderer() | 無需使用者介面控件 |
EnsureCoreWebView2Async() | 不適用 | 無需初始化 |
NavigateToString(html) + PrintToPdfAsync() | RenderHtmlAsPdf(html) | 單方法調用 |
Navigate(url) + PrintToPdfAsync() | RenderUrlAsPdf(url) | 單方法調用 |
PrintSettings.PageWidth | RenderingOptions.PaperSize | 使用 PdfPaperSize 列舉 |
PrintSettings.PageHeight | RenderingOptions.PaperSize | 使用 PdfPaperSize 列舉 |
PrintSettings.MarginTop | RenderingOptions.MarginTop | 單位是毫米,不是英寸 |
PrintSettings.Orientation | RenderingOptions.PaperOrientation | 人像/風景 |
ExecuteScriptAsync() | HTML 中的 JavaScript | 或使用 WaitFor 選項 |
AddScriptToExecuteOnDocumentCreatedAsync() | HTML 15 1000 1 15 1000 1 |




