跳至頁尾內容
影片

如何在 C# 中清理 PDF | IronPDF

WebView2, Microsoft 的嵌入式 Edge/Chromium 瀏覽器控制項 (Microsoft.Web.WebView2),為開發者提供了一種在 Windows 應用程式中顯示網頁內容的方法。 然而,當開發團隊嘗試使用 WebView2 進行 PDF 生成時,會遇到架構上的限制,這使得它不適合用於無頭和伺服器場景。 WebView2 是一種為 UI 應用設計的瀏覽器嵌入控制項,並不是 PDF 生成程式庫。

本指南提供從 WebView2 遷移到IronPDF的路徑,包含程式碼比較和一個實用的範例,適合需要可靠 PDF 生成的 .NET 開發者。

為什麼 WebView2 不適合做 PDF 生成

在檢視遷移路徑之前,了解一下為什麼 WebView2 不適合無頭 PDF 建立有幫助:

問題 影響 嚴重性
記憶體洩漏 在長時間運行的進程中報告的記憶體增長,這些進程反覆建立 WebView2 實例。
僅限 Windows 不支持 Linux、macOS、Docker 或非 Windows 的雲環境 關鍵
需要 UI 執行緒 必須在包含消息泵的 STA 執行緒上運行。不適用於 Web 伺服器或背景 API。 關鍵
非能為 PDF 設計 PrintToPdfAsync 是次要的能力,非核心功能
在服務中不穩定 在 Windows 服務和背景工作中報告的崩潰和卡死
復雜的異步流 導航事件、完成回調、競賽條件
Edge 執行環境的依存性 需要目標計算機上安裝 Edge WebView2 執行環境 中等
無頭模式 圍繞 UI 控制進行設計; 不是無頭渲染器 中等
性能 啟動緩慢,資源消耗大 中等
沒有 PDF 支持故事 Microsoft 並不將 WebView2 定位為 PDF 生成產品 中等

真實世界的失敗場景

這些程式碼模式通常在生產中引起問題:

// WARNING: These patterns are known to cause problems in headless / server scenarios

//問題1: Memory growth - creates a new WebView2 per PDF
public async Task<byte[]> GeneratePdf(string html) // High call volume accumulates memory
{
    using var webView = new WebView2(); // Disposal does not fully reclaim native resources
    await webView.EnsureCoreWebView2Async();
    webView.CoreWebView2.NavigateToString(html);
    // ... memory growth reported over time
}

//問題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
    }
}
// WARNING: These patterns are known to cause problems in headless / server scenarios

//問題1: Memory growth - creates a new WebView2 per PDF
public async Task<byte[]> GeneratePdf(string html) // High call volume accumulates memory
{
    using var webView = new WebView2(); // Disposal does not fully reclaim native resources
    await webView.EnsureCoreWebView2Async();
    webView.CoreWebView2.NavigateToString(html);
    // ... memory growth reported over time
}

//問題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
    }
}
' WARNING: These patterns are known to cause problems in headless / server scenarios

'問題1: Memory growth - creates a new WebView2 per PDF
Public Async Function GeneratePdf(html As String) As Task(Of Byte()) ' High call volume accumulates memory
    Using webView As New WebView2() ' Disposal does not fully reclaim native resources
        Await webView.EnsureCoreWebView2Async()
        webView.CoreWebView2.NavigateToString(html)
        ' ... memory growth reported over time
    End Using
End Function

'問題2: UI thread requirement - crashes in ASP.NET
Public Function GenerateReport() As IActionResult ' FAILS - no STA thread
    Dim webView As New WebView2() ' InvalidOperationException
    ' Additional logic needed to handle UI thread requirement
    Return Nothing
End Function

'問題3: Windows Service instability
Public Class PdfService
    Inherits BackgroundService ' Random crashes

    Protected Overrides Async Function ExecuteAsync(token As CancellationToken) As Task
        ' WebView2 + no message pump = hangs, crashes, undefined behavior
    End Function
End Class
$vbLabelText   $csharpLabel

IronPDF與 WebView2: 功能比較

了解結構差異有助於技術決策者評估遷移投資:

方面 WebView2 IronPDF
用途 瀏覽器控制(UI) PDF 程式庫(用於 PDF 設計)
投產準備
記憶體管理 在長時間運行中報告的記憶體增長 穩定,適當處理
平台支持 僅限於Windows Windows, Linux, macOS, Docker
執行緒要求 STA + 消息泵 支持任何執行緒
伺服器/雲 不支持 支援
Azure/AWS/GCP 有問題 完美運作
Docker 不可能 提供官方映像
ASP.NET Core 無法工作 一流支持
背景服務 不穩定 穩定
支持的上下文 僅限 WinForms/WPF 任何 .NET 上下文:控制台、網頁桌面
HTML 到 PDF 基本 全面
URL至PDF 基本 全面
頁首/頁尾 是(HTML)
水印
合併PDF
分割PDF
數位簽名
密碼保護
PDF/A合規性
專業支持 無 PDF 支持
文件 有限 廣泛的

快速開始:從 WebView2 遷移到 IronPDF

可以立即透過這些基本步驟開始遷移。

步驟 1:移除 WebView2 套件

dotnet remove package Microsoft.Web.WebView2
dotnet remove package Microsoft.Web.WebView2
SHELL

或者從您的專案文件中移除:


<PackageReference Include="Microsoft.Web.WebView2" Version="*" Remove />

<PackageReference Include="Microsoft.Web.WebView2" Version="*" Remove />
XML

步驟 2:安裝 IronPDF

dotnet add package IronPdf

步驟 3:更新命名空間

用IronPDF命名空間替換 WebView2 命名空間:

// 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;
Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2.WinForms

' After (IronPDF)
Imports IronPdf
$vbLabelText   $csharpLabel

步驟 4:初始化授權

在應用啓動時新增授權初始化:

IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

程式碼遷移範例

將HTML轉換為PDF

最基本的操作揭示了這些 .NET PDF 方法之間的複雜性差異。

WebView2 方法:

// NuGet: Install-Package Microsoft.Web.WebView2
// (the WinForms host lives in the same package; no separate .WinForms package)
// Requires the Edge WebView2 Runtime installed on the target machine. Windows-only.
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);

        // PrintToPdfAsync(path, settings) returns Task<bool>; null = default settings
        bool ok = await webView.CoreWebView2.PrintToPdfAsync("output.pdf", null);
    }
}
// NuGet: Install-Package Microsoft.Web.WebView2
// (the WinForms host lives in the same package; no separate .WinForms package)
// Requires the Edge WebView2 Runtime installed on the target machine. Windows-only.
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);

        // PrintToPdfAsync(path, settings) returns Task<bool>; null = default settings
        bool ok = await webView.CoreWebView2.PrintToPdfAsync("output.pdf", null);
    }
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports Microsoft.Web.WebView2.WinForms
Imports Microsoft.Web.WebView2.Core

Module Program
    Async Function Main() As Task
        Dim webView As New WebView2()
        Await webView.EnsureCoreWebView2Async()

        webView.CoreWebView2.NavigateToString("<html><body><h1>Hello World</h1></body></html>")
        Await Task.Delay(2000)

        ' PrintToPdfAsync(path, settings) returns Task(Of Boolean); Nothing = default settings
        Dim ok As Boolean = Await webView.CoreWebView2.PrintToPdfAsync("output.pdf", Nothing)
    End Function
End Module
$vbLabelText   $csharpLabel

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");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Hello World</h1></body></html>")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

WebView2 版本需要包含 EnsureCoreWebView2Async() 的異步初始化,使用 NavigateToString() 的導航,等待渲染的 Task.Delay(2000),以及最後返回 Task<bool> 表示成功的 PrintToPdfAsync 呼叫。IronPDF消除了這些繁瑣——建立一個渲染器、渲染 HTML、保存。

如需進階 HTML 到 PDF 的場景,請參見 HTML 到 PDF 轉換指南

將 URL 轉換為 PDF

URL 到 PDF 的轉換展示了 WebView2 的複雜異步導航流程。

WebView2 方法:

// NuGet: Install-Package Microsoft.Web.WebView2
// (Edge Chromium control; requires Edge WebView2 Runtime; Windows-only.)
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
// (Edge Chromium control; requires Edge WebView2 Runtime; Windows-only.)
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));
    }
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports Microsoft.Web.WebView2.WinForms
Imports Microsoft.Web.WebView2.Core

Module Program
    Async Function Main() As Task
        Dim webView As New WebView2()
        Await webView.EnsureCoreWebView2Async()

        Dim tcs As New TaskCompletionSource(Of Boolean)()
        AddHandler webView.CoreWebView2.NavigationCompleted, Sub(s, e) tcs.SetResult(True)

        webView.CoreWebView2.Navigate("https://example.com")
        Await tcs.Task
        Await Task.Delay(1000)

        Dim result As String = Await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
            "Page.printToPDF",
            "{""printBackground"": true}"
        )

        Dim base64 As String = System.Text.Json.JsonDocument.Parse(result).RootElement.GetProperty("data").GetString()
        File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64))
    End Function
End Module
$vbLabelText   $csharpLabel

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");
    }
}
Imports IronPdf

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

WebView2 需要建立一個 TaskCompletionSource,訂閱 NavigationCompleted 事件,呼叫 CallDevToolsProtocolMethodAsync,解析 JSON 響應,並手動解碼 base64 資料。IronPDF提供一個專用的 RenderUrlAsPdf 方法,這個方法在內部處理所有複雜性。

查看 URL 到 PDF 文件,了解認證和自定義標頭選項。

從 HTML 文件生成自定義 PDF 設置

配置頁面方向、邊距和紙張大小需要不同的方法。

WebView2 方法:

// NuGet: Install-Package Microsoft.Web.WebView2
// CreatePrintSettings() lives on CoreWebView2Environment.
// Margin* / PageWidth / PageHeight on CoreWebView2PrintSettings are in INCHES.
// PrintToPdfAsync(path, settings) returns Task<bool> (true on success) — not a stream.
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);

        CoreWebView2PrintSettings printSettings = webView.CoreWebView2.Environment.CreatePrintSettings();
        printSettings.Orientation = CoreWebView2PrintOrientation.Landscape;
        printSettings.MarginTop = 0.5;     // inches
        printSettings.MarginBottom = 0.5;  // inches
        printSettings.ShouldPrintBackgrounds = true;

        bool ok = await webView.CoreWebView2.PrintToPdfAsync("custom.pdf", printSettings);
        Console.WriteLine(ok ? "Custom PDF created" : "PrintToPdfAsync returned false");
    }
}
// NuGet: Install-Package Microsoft.Web.WebView2
// CreatePrintSettings() lives on CoreWebView2Environment.
// Margin* / PageWidth / PageHeight on CoreWebView2PrintSettings are in INCHES.
// PrintToPdfAsync(path, settings) returns Task<bool> (true on success) — not a stream.
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);

        CoreWebView2PrintSettings printSettings = webView.CoreWebView2.Environment.CreatePrintSettings();
        printSettings.Orientation = CoreWebView2PrintOrientation.Landscape;
        printSettings.MarginTop = 0.5;     // inches
        printSettings.MarginBottom = 0.5;  // inches
        printSettings.ShouldPrintBackgrounds = true;

        bool ok = await webView.CoreWebView2.PrintToPdfAsync("custom.pdf", printSettings);
        Console.WriteLine(ok ? "Custom PDF created" : "PrintToPdfAsync returned false");
    }
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports Microsoft.Web.WebView2.Core
Imports Microsoft.Web.WebView2.WinForms

Module Program
    Async Function Main() As Task
        Dim webView As New WebView2()
        Await webView.EnsureCoreWebView2Async()

        Dim htmlFile As String = Path.Combine(Directory.GetCurrentDirectory(), "input.html")
        webView.CoreWebView2.Navigate(htmlFile)

        Await Task.Delay(3000)

        Dim printSettings As CoreWebView2PrintSettings = webView.CoreWebView2.Environment.CreatePrintSettings()
        printSettings.Orientation = CoreWebView2PrintOrientation.Landscape
        printSettings.MarginTop = 0.5 ' inches
        printSettings.MarginBottom = 0.5 ' inches
        printSettings.ShouldPrintBackgrounds = True

        Dim ok As Boolean = Await webView.CoreWebView2.PrintToPdfAsync("custom.pdf", printSettings)
        Console.WriteLine(If(ok, "Custom PDF created", "PrintToPdfAsync returned false"))
    End Function
End Module
$vbLabelText   $csharpLabel

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");
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Imports System.IO

Module Program
    Sub Main()
        Dim renderer As New ChromePdfRenderer()

        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
        renderer.RenderingOptions.MarginTop = 50
        renderer.RenderingOptions.MarginBottom = 50

        Dim htmlFile As String = Path.Combine(Directory.GetCurrentDirectory(), "input.html")
        Dim pdf = renderer.RenderHtmlFileAsPdf(htmlFile)
        pdf.SaveAs("custom.pdf")

        Console.WriteLine("Custom PDF created")
    End Sub
End Module
$vbLabelText   $csharpLabel

WebView2 需要一個 3 秒的 Task.Delay(不可靠的估計),通過 CoreWebView2.Environment 建立列印設置,以及對 PrintToPdfAsync(path, settings) 進行的 await,該設定返回 Task<bool> 而不是流。 WebView2 用英寸表達邊距;IronPDF通過直接的 RenderingOptions 屬性使用毫米。

使用開發工具協議的高級 PDF 選項

複雜的 WebView2 配置需要開發工具協議交互。

WebView2 方法:

// NuGet: Install-Package Microsoft.Web.WebView2
// Uses raw Chrome DevTools Protocol via CallDevToolsProtocolMethodAsync.
// (Page.printToPDF returns base64 in result.data; units are inches.)
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
// Uses raw Chrome DevTools Protocol via CallDevToolsProtocolMethodAsync.
// (Page.printToPDF returns base64 in result.data; units are inches.)
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));
    }
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports System.Text.Json
Imports Microsoft.Web.WebView2.WinForms
Imports Microsoft.Web.WebView2.Core

Module Program
    Async Function Main() As Task
        Dim webView As New WebView2()
        Await webView.EnsureCoreWebView2Async()

        Dim htmlPath As String = Path.GetFullPath("document.html")
        Dim tcs As New TaskCompletionSource(Of Boolean)()
        AddHandler webView.CoreWebView2.NavigationCompleted, Sub(s, e) tcs.SetResult(True)

        webView.CoreWebView2.Navigate($"file:///{htmlPath}")
        Await tcs.Task
        Await Task.Delay(1000)

        Dim options = New With {
            .landscape = False,
            .printBackground = True,
            .paperWidth = 8.5,
            .paperHeight = 11,
            .marginTop = 0.4,
            .marginBottom = 0.4,
            .marginLeft = 0.4,
            .marginRight = 0.4
        }

        Dim result As String = Await webView.CoreWebView2.CallDevToolsProtocolMethodAsync(
            "Page.printToPDF",
            JsonSerializer.Serialize(options)
        )

        Dim base64 As String = JsonDocument.Parse(result).RootElement.GetProperty("data").GetString()
        File.WriteAllBytes("output.pdf", Convert.FromBase64String(base64))
    End Function
End Module
$vbLabelText   $csharpLabel

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");
    }
}
Imports IronPdf
Imports IronPdf.Rendering

Class Program
    Shared Sub Main()
        Dim 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

        Dim pdf = renderer.RenderHtmlFileAsPdf("document.html")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

WebView2 需要構造匿名物件,序列化為 JSON,呼叫 DevTools Protocol 方法,解析 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
PrintSettings.PageHeight RenderingOptions.PaperSize
PrintSettings.MarginTop RenderingOptions.MarginTop
PrintSettings.Orientation RenderingOptions.PaperOrientation
ExecuteScriptAsync() HTML中的JavaScript
AddScriptToExecuteOnDocumentCreatedAsync() HTML <script> 標籤
導航事件 WaitFor.JavaScript()
CallDevToolsProtocolMethodAsync("Page.printToPDF") RenderHtmlAsPdf()

常見遷移問題及解決方案

問題 1:記憶體增長

WebView2 問題:記憶體增長報告在長時間運行的進程中,這些進程重複建立 WebView2 實例,尤其在沒有穩定的消息泵的情況下。

IronPDF 解決方案:可預測的消除和 using 良好的生命週期:

//IronPDF- clean memory management
using (var pdf = renderer.RenderHtmlAsPdf(html))
{
    pdf.SaveAs("output.pdf");
} // Properly disposed
//IronPDF- clean memory management
using (var pdf = renderer.RenderHtmlAsPdf(html))
{
    pdf.SaveAs("output.pdf");
} // Properly disposed
Imports IronPdf

Using pdf = renderer.RenderHtmlAsPdf(html)
    pdf.SaveAs("output.pdf")
End Using
$vbLabelText   $csharpLabel

問題 2:網頁應用中沒有 UI 執行緒

WebView2 問題:需要包含消息泵的 STA 執行緒。ASP.NET Core 控制器無法建立 WebView2 實例。

IronPDF 解決方案:支援任何執行緒:

// ASP.NET Core - just works
public async Task<IActionResult> GetPdf()
{
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
// ASP.NET Core - just works
public async Task<IActionResult> GetPdf()
{
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc

Public Class YourController
    Inherits Controller

    Public Async Function GetPdf() As Task(Of IActionResult)
        Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
        Return File(pdf.BinaryData, "application/pdf")
    End Function
End Class
$vbLabelText   $csharpLabel

問題 3:導航事件複雜性

WebView2 問題:必須處理 TaskCompletionSource 的異步導航事件、完成回調以及競賽條件。

IronPDF 解決方案:同步或異步單一方法呼叫:

// Simple and predictable
var pdf = renderer.RenderHtmlAsPdf(html);
// or
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
// Simple and predictable
var pdf = renderer.RenderHtmlAsPdf(html);
// or
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
$vbLabelText   $csharpLabel

問題 4:測量單位

WebView2 使用英寸為尺寸單位(如:8.5 x 11 用於 Letter)。 IronPDF 使用毫米提供更精確的尺寸。

轉換方法:

// WebView2: PageWidth = 8.27 (inches for A4)
// IronPDF: Use enum
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

// Or custom size in mm
renderer.RenderingOptions.SetCustomPaperSizeInMillimeters(210, 297);
// WebView2: PageWidth = 8.27 (inches for A4)
// IronPDF: Use enum
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

// Or custom size in mm
renderer.RenderingOptions.SetCustomPaperSizeInMillimeters(210, 297);
' WebView2: PageWidth = 8.27 (inches for A4)
' IronPDF: Use enum
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4

' Or custom size in mm
renderer.RenderingOptions.SetCustomPaperSizeInMillimeters(210, 297)
$vbLabelText   $csharpLabel

WebView2 遷移檢查表

遷移前任務

記錄您程式碼庫中所有 WebView2 PDF 生成程式碼。 確定 WebView2 引起問題的地方(記憶體洩漏、崩潰、部署問題)。 查看 IronPDF 文件 以熟悉其功能。

程式碼更新任務

  1. 移除 Microsoft.Web.WebView2 NuGet 套件
  2. 安裝IronPDFNuGet 套件
  3. 如僅用於 PDF 生成,移除 WinForms/WPF 依賴
  4. ChromePdfRenderer 替換 WebView2 程式碼
  5. 移除 STA 執行緒要求
  6. 移除導航事件處理程式和 TaskCompletionSource 模式
  7. 移除 Task.Delay 破解
  8. 在啟動時新增IronPDF授權初始化

遷移後測試

遷移後,驗證以下方面:

  • 在目標環境中測試(如適用,ASP.NET、Docker、Linux)
  • 驗證 PDF 輸出質量符合期望
  • 測試包含大量 JavaScript 的頁面是否正確呈現
  • 驗證頁眉和頁腳是否能與IronPDF的 HTML 功能協同運作
  • 在長期運行的操作中測試記憶體穩定性
  • 測試無記憶體累積的長時間運行場景

部署更新

  • 如適用,更新 Docker 映像(移除 Edge WebView2 執行環境)
  • 從伺服器需求中移除 Edge WebView2 執行環境依賴
  • 更新伺服器需求文件
  • 驗證跨平台部署是否能在目標平台上運行

請注意WebView2 是其各自擁有者的註冊商標。 此網站與Microsoft無關,也未獲其認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話