從 Haukcode.DinkToPdf 遷移到 IronPDF
Haukcode.DinkToPdf 是曾經流行的 DinkToPdf 庫的延續,它使用 wkhtmltopdf 二進位檔案將 HTML 轉換為 PDF,供 .NET 應用程式使用。 儘管 Haukcode.DinkToPdf 在原始專案停滯後繼續支援 .NET Core,但它由於其上游依賴項而存在嚴重的安全性問題。 wkhtmltopdf 專案已於 2023 年 1 月存檔,因此這些問題將永遠無法解決。
本指南提供了從 Haukcode.DinkToPdf 到IronPDF的完整遷移路徑,包括逐步說明、程式碼比較和實用範例,旨在幫助專業的 .NET 開發人員消除 PDF 生成工作流程中的安全風險。
重要安全警告:CVE-2022-35583
Haukcode.DinkToPdf 繼承了 wkhtmltopdf 的一個無法解決的重大安全漏洞:
CVE-2022-35583 - 關鍵 SSRF 漏洞 (CVSS 9.8)
wkhtmltopdf 函式庫(以及包括 Haukcode.DinkToPdf 在內的所有包裝程式)容易受到伺服器端請求偽造 (SSRF) 的攻擊:
攻擊途徑:惡意 HTML 內容可導致伺服器取得內部資源。
- AWS 元資料攻擊:可存取
http://169.254.169.254以竊取 AWS 憑證 -內部網路存取:可掃描和存取內部服務 -本機檔案包含:可透過file://協定讀取本機文件 影響:可能完全接管基礎設施
此漏洞沒有修復程式,因為 wkhtmltopdf 已於 2023 年廢棄並歸檔。最後發行的版本是 2020 年的 0.12.6 版。
IronPDFvs Haukcode.DinkToPdf:功能比較
了解架構上的差異有助於技術決策者評估遷移投資:
| 範疇 | Haukcode.DinkToPdf | IronPDF |
|---|---|---|
| 基礎引擎 | wkhtmltopdf (Qt WebKit ~2015) | Chromium (定期更新) |
| 安全狀態 | CVE-2022-35583 (CRITICAL, unfixable) | 積極修補 |
| 專案狀態 | 廢棄專案的分叉 | 積極開發 |
| HTML5/CSS3。 | 限額 | 支援 |
| JavaScript。 | 有限、不安全 | 完整的 V8 引擎 |
| 原生二進位 | 必需(特定平台) | 自成一格 |
| 線程安全 | 需要單元模式 | 線程安全的設計 |
| <強>支援</強 | 僅限社群 | 專業支援 |
| 更新 | 無預期 | 定期發佈 |
| 執照 | MIT (免費) | 免費試用的商業版 |
快速入門:Haukcode.DinkToPdf 到IronPDF的遷移。
只要完成這些基本步驟,就可以立即開始遷移。
步驟 1:移除 DinkToPdf 和原生二進位檔案
移除 Haukcode.DinkToPdf NuGet 套件:
# Remove NuGet packages
dotnet remove package DinkToPdf
dotnet remove package Haukcode.DinkToPdf
dotnet remove package Haukcode.WkHtmlToPdf-DotNet
# Remove NuGet packages
dotnet remove package DinkToPdf
dotnet remove package Haukcode.DinkToPdf
dotnet remove package Haukcode.WkHtmlToPdf-DotNet
從專案中刪除原生二進檔:
libwkhtmltox.dll(Windows)libwkhtmltox.so(Linux)libwkhtmltox.dylib(macOS)
步驟 2:安裝 IronPDF
# Install IronPDF
dotnet add package IronPdf
# Install IronPDF
dotnet add package IronPdf
步驟 3:更新命名空間
用IronPDF取代 DinkToPdf 命名空間:
// Before (Haukcode.DinkToPdf)
using DinkToPdf;
using DinkToPdf.Contracts;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering; // For RenderingOptions
// Before (Haukcode.DinkToPdf)
using DinkToPdf;
using DinkToPdf.Contracts;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering; // For RenderingOptions
Imports IronPdf
Imports IronPdf.Rendering
步驟 4:初始化授權
在應用程式啟動時加入授權初始化:
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
程式碼遷移範例
基本 HTML 到 PDF 的轉換
最基本的操作揭示了這些 .NET PDF 函式庫的複雜性差異。
Haukcode.DinkToPdf 方法:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
},
Objects = {
new ObjectSettings() {
HtmlContent = "<html><body><h1>Hello World</h1></body></html>",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
},
Objects = {
new ObjectSettings() {
HtmlContent = "<html><body><h1>Hello World</h1></body></html>",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("output.pdf", pdf);
}
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = New List(Of ObjectSettings) From {
New ObjectSettings() With {
.HtmlContent = "<html><body><h1>Hello World</h1></body></html>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("output.pdf", pdf)
End Sub
End Module
IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using System.IO;
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;
using System.IO;
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
Imports System.IO
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
Haukcode.DinkToPdf 需要建立一個 SynchronizedConverter 和 PdfTools,建構一個 HtmlToPdfDocument 和嵌套的 GlobalSettings 和 @@--CODE-16217--@@,添加一個 @@--CODE-16218--@@ 與 HtmlContent,呼叫 converter.Convert() 取得原始位元組,並使用 File.WriteAllBytes() 手動寫入檔案。
IronPDF 將此簡化為三行:建立一個 ChromePdfRenderer,呼叫 RenderHtmlAsPdf(),並使用內建的 SaveAs() 方法。
如需進階的 HTML 至IronPDF情境,請參閱 HTML 至 PDF 轉換指南。
將 URL 轉換為 PDF
URL 到 PDF 的轉換也顯示出類似的模式差異。
Haukcode.DinkToPdf 方法:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
},
Objects = {
new ObjectSettings() {
Page = "https://www.example.com",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
},
Objects = {
new ObjectSettings() {
Page = "https://www.example.com",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("webpage.pdf", pdf);
}
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Portrait,
.PaperSize = PaperKind.A4
},
.Objects = New List(Of ObjectSettings) From {
New ObjectSettings() With {
.Page = "https://www.example.com"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("webpage.pdf", pdf)
End Sub
End Module
IronPDF 方法:
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
Haukcode.DinkToPdf 使用相同的文件建構模式,URL 格式為 ObjectSettings.Page。IronPDF提供了一個專門的 RenderUrlAsPdf() 方法,可以清楚地表達意圖。
探索URL至PDF文件的認證和自訂標頭選項。
自訂頁面設定
配置方向、紙張大小和頁邊需要不同的方法。
Haukcode.DinkToPdf 方法:
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.Letter,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings() {
HtmlContent = "<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("landscape.pdf", pdf);
}
}
// NuGet: Install-Package DinkToPdf
using DinkToPdf;
using DinkToPdf.Contracts;
using System.IO;
class Program
{
static void Main()
{
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
{
GlobalSettings = {
ColorMode = ColorMode.Color,
Orientation = Orientation.Landscape,
PaperSize = PaperKind.Letter,
Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
},
Objects = {
new ObjectSettings() {
HtmlContent = "<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>",
}
}
};
byte[] pdf = converter.Convert(doc);
File.WriteAllBytes("landscape.pdf", pdf);
}
}
Imports DinkToPdf
Imports DinkToPdf.Contracts
Imports System.IO
Module Program
Sub Main()
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument() With {
.GlobalSettings = New GlobalSettings() With {
.ColorMode = ColorMode.Color,
.Orientation = Orientation.Landscape,
.PaperSize = PaperKind.Letter,
.Margins = New MarginSettings() With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
},
.Objects = {
New ObjectSettings() With {
.HtmlContent = "<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>"
}
}
}
Dim pdf As Byte() = converter.Convert(doc)
File.WriteAllBytes("landscape.pdf", pdf)
End Sub
End Module
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.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>");
pdf.SaveAs("landscape.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.PaperOrientation = PdfPaperOrientation.Landscape;
renderer.RenderingOptions.MarginTop = 10;
renderer.RenderingOptions.MarginBottom = 10;
renderer.RenderingOptions.MarginLeft = 10;
renderer.RenderingOptions.MarginRight = 10;
var pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>");
pdf.SaveAs("landscape.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
renderer.RenderingOptions.MarginTop = 10
renderer.RenderingOptions.MarginBottom = 10
renderer.RenderingOptions.MarginLeft = 10
renderer.RenderingOptions.MarginRight = 10
Dim pdf = renderer.RenderHtmlAsPdf("<html><body><h1>Landscape Document</h1><p>Custom page settings</p></body></html>")
pdf.SaveAs("landscape.pdf")
End Sub
End Class
Haukcode.DinkToPdf 將設定嵌套在 GlobalSettings 中,並使用單獨的 MarginSettings 物件。IronPDF提供直接的 RenderingOptions 屬性,其名稱清晰明了,例如 PaperSize、PaperOrientation 以及單獨的邊距屬性。
Haukcode.DinkToPdf API 到IronPDF的映射參考。
此對應可透過顯示直接的 API 對應關係來加速遷移:
轉換器類別對應
| Haukcode.DinkToPdf | IronPDF |
|---|---|
SynchronizedConverter |
ChromePdfRenderer |
BasicConverter |
ChromePdfRenderer |
PdfTools |
不適用 |
IConverter |
不適用 |
文件配置映射
| Haukcode.DinkToPdf | IronPDF |
|---|---|
HtmlToPdfDocument |
方法調用 |
GlobalSettings |
RenderingOptions |
ObjectSettings |
RenderingOptions |
converter.Convert(doc) |
renderer.RenderHtmlAsPdf(html) |
GlobalSettings 屬性對應
| GlobalSettings 屬性 | IronPDF 特性 |
|---|---|
ColorMode |
RenderingOptions.GrayScale |
Orientation |
RenderingOptions.PaperOrientation |
PaperSize |
RenderingOptions.PaperSize |
Margins.Top |
RenderingOptions.MarginTop |
Margins.Bottom |
RenderingOptions.MarginBottom |
Margins.Left |
RenderingOptions.MarginLeft |
Margins.Right |
RenderingOptions.MarginRight |
物件設定屬性對應
| 物件設定屬性 | IronPDF 同等級產品 |
|---|---|
HtmlContent |
第一個參數給 RenderHtmlAsPdf() |
Page (URL) |
renderer.RenderUrlAsPdf(url) |
HeaderSettings.Right = "[page]" |
TextHeader.RightText = "{page}" |
占位符語法遷移
| Haukcode.DinkToPdf | IronPDF |
|---|---|
[page] |
{page} |
[toPage] |
{total-pages} |
[date] |
{date} |
常見的遷移問題與解決方案
問題 1:單元需求
Haukcode.DinkToPdf:由於原生 wkhtmltopdf 二進位檔案的線程安全問題,需要將 SynchronizedConverter 作為單例。
解決方案:IronPDF的 ChromePdfRenderer 從設計上就是線程安全的-不需要單例模式:
// Before (DinkToPdf) - MUST be singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
// After (IronPDF) - Can be singleton or transient (both work)
services.AddSingleton<IPdfService, IronPdfService>();
// Or services.AddTransient<IPdfService, IronPdfService>() - both are safe!
// Before (DinkToPdf) - MUST be singleton
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
// After (IronPDF) - Can be singleton or transient (both work)
services.AddSingleton<IPdfService, IronPdfService>();
// Or services.AddTransient<IPdfService, IronPdfService>() - both are safe!
' Before (DinkToPdf) - MUST be singleton
services.AddSingleton(GetType(IConverter), New SynchronizedConverter(New PdfTools()))
' After (IronPDF) - Can be singleton or transient (both work)
services.AddSingleton(Of IPdfService, IronPdfService)()
' Or services.AddTransient(Of IPdfService, IronPdfService)() - both are safe!
問題 2:原生二進位相依性
Haukcode.DinkToPdf:需要特定平台的本機庫 (libwkhtmltox.dll/so/dylib)。
解決方案:IronPDF是獨立的,沒有本機的二進位相依性。 遷移後刪除這些檔案:
libwkhtmltox.dll(Windows)libwkhtmltox.so(Linux)libwkhtmltox.dylib(macOS)
問題 3:回傳類型的差異
Haukcode.DinkToPdf: converter.Convert() 直接返回 byte[]。
解決方案:IronPDF傳回一個包含多個輸出選項的 PdfDocument 物件:
var pdf = renderer.RenderHtmlAsPdf(html);
byte[] bytes = pdf.BinaryData; // Get bytes
pdf.SaveAs("output.pdf"); // Or save directly
var pdf = renderer.RenderHtmlAsPdf(html);
byte[] bytes = pdf.BinaryData; // Get bytes
pdf.SaveAs("output.pdf"); // Or save directly
Dim pdf = renderer.RenderHtmlAsPdf(html)
Dim bytes As Byte() = pdf.BinaryData ' Get bytes
pdf.SaveAs("output.pdf") ' Or save directly
問題 4:頁首/頁尾占位符語法
Haukcode.DinkToPdf:使用方括號語法,例如 [page] 和 [toPage]。
解決方案:更新IronPDF的大括弧占位符:
// Before (DinkToPdf)
HeaderSettings = { Right = "Page [page] of [toPage]" }
// After (IronPDF)
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
RightText = "Page {page} of {total-pages}"
};
// Before (DinkToPdf)
HeaderSettings = { Right = "Page [page] of [toPage]" }
// After (IronPDF)
renderer.RenderingOptions.TextHeader = new TextHeaderFooter
{
RightText = "Page {page} of {total-pages}"
};
' Before (DinkToPdf)
HeaderSettings = New With {.Right = "Page [page] of [toPage]"}
' After (IronPDF)
renderer.RenderingOptions.TextHeader = New TextHeaderFooter With {
.RightText = "Page {page} of {total-pages}"
}
Haukcode.DinkToPdf 移轉清單
遷移前的任務
審核您的程式碼庫,找出所有 DinkToPdf 的使用情況:
# Find DinkToPdf namespace usage
grep -r "using DinkToPdf\|using Haukcode" --include="*.cs" .
# Find converter usage
grep -r "SynchronizedConverter\|BasicConverter\|HtmlToPdfDocument" --include="*.cs" .
# Find native library loading
grep -r "wkhtmltopdf\|libwkhtmltox" --include="*.cs" --include="*.csproj" .
# Find GlobalSettings/ObjectSettings usage
grep -r "GlobalSettings\|ObjectSettings\|MarginSettings" --include="*.cs" .
# Find DinkToPdf namespace usage
grep -r "using DinkToPdf\|using Haukcode" --include="*.cs" .
# Find converter usage
grep -r "SynchronizedConverter\|BasicConverter\|HtmlToPdfDocument" --include="*.cs" .
# Find native library loading
grep -r "wkhtmltopdf\|libwkhtmltox" --include="*.cs" --include="*.csproj" .
# Find GlobalSettings/ObjectSettings usage
grep -r "GlobalSettings\|ObjectSettings\|MarginSettings" --include="*.cs" .
記錄目前的 GlobalSettings 和 ObjectSettings 配置。 找出任何可以移除的本機庫載入程式碼。
程式碼更新任務
1.移除 DinkToPdf NuGet 套件 2.安裝IronPDFNuGet 套件
- 將命名空間導入從
DinkToPdf更新為IronPdf - 將
SynchronizedConverter替換為ChromePdfRenderer - 將
HtmlToPdfDocument模式轉換為直接方法調用 - 將
GlobalSettings轉換為RenderingOptions - 將
ObjectSettings轉換為RenderingOptions - 更新佔位語法(
[page]→{page},[toPage]→{total-pages}) 9.在啟動時增加IronPDF授權初始化功能
基礎結構清理任務
1.刪除原生二進位檔 (libwkhtmltox.*) 2.移除原生程式庫載入程式碼 3.如果存在,移除 CustomAssemblyLoadContext 4.更新依賴注入 (不再需要單件) 5.移除原生二進位檔的平台偵測程式碼
後遷移測試
轉移後,驗證這些方面:
- 測試 HTML 至 PDF 的轉換
- 測試 URL 至 PDF 的轉換
- 確認頁面設定(大小、方向、邊界)
- 使用占位符驗證頁首和頁尾
- 使用實際的 HTML 範本進行測試
- 負載下的效能測試
遷移到IronPDF的主要優點。
從 Haukcode.DinkToPdf 轉移到IronPDF提供了幾個關鍵優勢:
安全性:消除 CVE-2022-35583 (SSRF) 和其他 wkhtmltopdf 漏洞,這些漏洞永遠不會被修復。
現代渲染引擎:使用持續更新的 Chromium 內核,而不是 2015 年就已棄用的 Qt WebKit 內核。完全支援 HTML5、CSS3 和 JavaScript。
無本地二進位檔案:自包含庫,無需管理任何平台特定的 DLL 檔案。 簡化跨 Windows、Linux 和 macOS 的部署。
線程安全:沒有單例要求-可以在任何模式中自由使用 ChromePdfRenderer,包括按請求實例化。
更簡單的 API:直接方法呼叫(RenderHtmlAsPdf(),RenderUrlAsPdf()),而不是複雜的文檔物件建構。
積極開發:隨著 .NET 10 和 C# 14 的普及,IronPDF 將持續更新,確保與目前和未來的 .NET 版本相容。

