跳至页脚内容
迁移指南

如何用 C# 从 PrinceXML 迁移到 IronPDF

从PrinceXML迁移到IronPDF可将您的 PDF 生成工作流程从外部命令行流程转换为本地 .NET 库。 本指南提供了一个完整的、循序渐进的迁移路径,可消除流程管理开销,简化部署,并提供生成之外的广泛 PDF 操作功能。

为什么要从PrinceXML迁移到 IronPDF.

了解 PrinceXML

PrinceXML 是一款复杂的工具,通过专门支持 CSS 分页媒体规范,可将 HTML 内容转换为打印效果完美的 PDF 文档。 这种专业性使PrinceXML能够高保真地按照预期的印刷设计渲染文档,这对于需要详细印刷样式的行业(如出版或法律文档)来说是非常有价值的。

不过,PrinceXML 并非 .NET 库,而是作为一个单独的命令行工具运行,这可能会使偏好纯 .NET 解决方案的环境的集成变得复杂。 对独立服务器进程的依赖涉及额外的系统资源管理,并可能增加项目部署的复杂性。

外部流程问题

PrinceXML 作为一个独立的命令行可执行文件运行,这给 .NET 应用程序带来了巨大的架构挑战:

1.进程管理开销:必须生成、监控和终止外部进程。

2.不支持原生 .NET 集成:通过 stdin/stdout 或临时文件进行通信。

3.部署复杂性:需要在每台服务器上安装 Prince。

4.按服务器许可:每次部署都需要单独的许可证(495 美元以上)。

5.错误处理难度:解析文本输出以进行错误检测。

6.无需 Async/await:无需阻塞调用或复杂的异步包装器。

7.路径依赖:必须在 PATH 或绝对路径中找到 Prince 可执行文件。

PrinceXML与IronPDF对比

方面 PrinceXML IronPDF
架构 外部流程 本地 .NET 库
集成 命令行 直接应用程序接口
部署 在每台服务器上安装 单个 NuGet 软件包
错误处理 解析文本输出 .NET 例外情况
支持同步 手册包装 本地 async/await
PDF 操作 仅生成 全面操作(合并、拆分、编辑)
许可 每台服务器(495 美元以上) 每位开发人员
更新 手动重新安装 NuGet 更新
调试 难点 完全支持调试器
数字签名
表格
Docker 支持 复杂 简单的
云函数 难点 简易

IronPDF for .NET 凭借其 .NET 原生功能提供了另一种选择,它不仅仅是 HTML 到 PDF 的转换,还包括高级 PDF 操作任务,如编辑、合并和数字签名。IronPDF的 API 设计简单易用,开发人员只需使用最少的模板代码即可执行转换和操作。

对于计划在 2025 年和 2026 年之前采用 .NET 10 和 C# 14 的团队来说,IronPDF 的无缝部署不需要外部依赖或服务器进程,因此减轻了集成到 .NET Framework 的负担。


开始之前

前提条件

  1. .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
  2. NuGet 访问权限:能够安装 NuGet 包
  3. IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。

NuGet 软件包变更

# Install IronPDF
dotnet add package IronPdf

# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper
# Install IronPDF
dotnet add package IronPdf

# Remove Prince wrapper if using one
dotnet remove package PrinceXMLWrapper
SHELL

许可配置

// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

搜索PrinceXML使用情况

# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .
# Find Prince process calls
grep -r "prince" --include="*.cs" .
grep -r "Process.Start" --include="*.cs" . | grep -i prince
grep -r "@page" --include="*.css" .
grep -r "prince-" --include="*.css" .
SHELL

完整的 API 参考

命名空间变更

// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;

// After: IronPDF
using IronPdf;
// Before: PrinceXML
using PrinceXMLWrapper;
using System.Diagnostics;
using System.IO;

// After: IronPDF
using IronPdf;
' Before: PrinceXML
Imports PrinceXMLWrapper
Imports System.Diagnostics
Imports System.IO

' After: IronPDF
Imports IronPdf
$vbLabelText   $csharpLabel

命令行到方法映射

王子命令 IronPDF 同等产品
prince input.html -o output.pdf renderer.RenderHtmlFileAsPdf("input.html").SaveAs("output.pdf")
prince --style=custom.css input.html 在 HTML 中包含 CSS 或使用 RenderingOptions
prince --javascript renderer.RenderingOptions.EnableJavaScript = true
prince --no-javascript renderer.RenderingOptions.EnableJavaScript = false
prince --page-size=Letter renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
prince --page-margin=1in renderer.RenderingOptions.MarginTop = 72(72 点 = 1 英寸)
prince --encrypt pdf.SecuritySettings.OwnerPassword = "..."
prince --user-password=pw pdf.SecuritySettings.UserPassword = "pw"
prince --disallow-print pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
prince --disallow-copy pdf.SecuritySettings.AllowUserCopyPasteContent = false
prince --baseurl=http://... renderer.RenderingOptions.BaseUrl = new Uri("http://...")
prince --media=print renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print
prince --media=screen renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Screen

CSS @page 到 RenderingOptions 映射

CSS @page 属性 IronPDF 同等产品
size: A4 PaperSize = PdfPaperSize.A4
size: Letter PaperSize = PdfPaperSize.Letter
size:A4landscape PaperSize = PdfPaperSize.A4 + PaperOrientation = Landscape
margin: 2cm MarginTop/Bottom/Left/Right = 56
margin-top: 1in MarginTop = 72
@top-center { content: "..." } HtmlHeader 带有居中 div
@bottom-right { content: counter(page) } HtmlFooter{page} 占位符

页面大小转换

规模 翻译要点 毫米
信函 612 x 792 216 x 279
A4 595 x 842 210 x 297
法律 612 x 1008 216 x 356
1 英寸 72 25.4
1 厘米 28.35 10

代码迁移示例

示例 1:HTML 文件到 PDF 的转换

之前 (PrinceXML):

// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("input.html", "output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("input.html", "output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
Imports PrinceXMLWrapper
Imports System

Module Program
    Sub Main()
        Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
        prince.Convert("input.html", "output.pdf")
        Console.WriteLine("PDF created successfully")
    End Sub
End Module
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created successfully")
    End Sub
End Class
$vbLabelText   $csharpLabel

本例展示了基本的架构差异。PrinceXML需要实例化一个 Prince 对象,并传入可执行文件的完整路径 ("C:\\Program Files\\Prince\\engine\\bin\\prince.exe"),然后调用 Convert() 并传入输入和输出路径。

IronPDF 完全消除了路径依赖:创建一个 ChromePdfRenderer,使用 HTML 文件路径调用 RenderHtmlFileAsPdf(),然后使用 SaveAs() 写入结果。 无执行路径、无流程管理、无路径依赖。 请参阅 HTML 转 PDF 文档,了解全面的示例。

示例 2:带选项的 URL 到 PDF 转换

之前 (PrinceXML):

// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.SetJavaScript(true);
        prince.SetEncrypt(true);
        prince.SetPDFTitle("Website Export");
        prince.Convert("https://example.com", "webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;

class Program
{
    static void Main()
    {
        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.SetJavaScript(true);
        prince.SetEncrypt(true);
        prince.SetPDFTitle("Website Export");
        prince.Convert("https://example.com", "webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
Imports PrinceXMLWrapper
Imports System

Class Program
    Shared Sub Main()
        Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
        prince.SetJavaScript(True)
        prince.SetEncrypt(True)
        prince.SetPDFTitle("Website Export")
        prince.Convert("https://example.com", "webpage.pdf")
        Console.WriteLine("URL converted to PDF")
    End Sub
End Class
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.EnableJavaScript = true;
        renderer.RenderingOptions.PdfTitle = "Website Export";

        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.Encrypt("password");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.EnableJavaScript = true;
        renderer.RenderingOptions.PdfTitle = "Website Export";

        var pdf = renderer.RenderUrlAsPdf("https://example.com");
        pdf.Encrypt("password");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("URL converted to PDF");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        renderer.RenderingOptions.EnableJavaScript = True
        renderer.RenderingOptions.PdfTitle = "Website Export"

        Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
        pdf.Encrypt("password")
        pdf.SaveAs("webpage.pdf")
        Console.WriteLine("URL converted to PDF")
    End Sub
End Class
$vbLabelText   $csharpLabel

本例展示了PrinceXML选项如何映射到IronPDF属性。PrinceXML在转换之前使用 setter 方法(SetJavaScript()SetEncrypt()SetPDFTitle())。IronPDF使用 RenderingOptions 属性进行预渲染设置,以及 Encrypt() 对象上的后渲染方法。

关键映射:

  • prince.SetJavaScript(true)renderer.RenderingOptions.EnableJavaScript = true
  • prince.SetPDFTitle("...")renderer.RenderingOptions.PdfTitle = "..."
  • prince.SetEncrypt(true)pdf.Encrypt("password") (IronPDF 需要密码)

在我们的教程中了解更多信息。

示例 3:HTML 字符串到 PDF 的转换

之前 (PrinceXML):

// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
        File.WriteAllText("temp.html", html);

        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("temp.html", "styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
// NuGet: Install-Package PrinceXMLWrapper
using PrinceXMLWrapper;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";
        File.WriteAllText("temp.html", html);

        Prince prince = new Prince("C:\\Program Files\\Prince\\engine\\bin\\prince.exe");
        prince.Convert("temp.html", "styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
Imports PrinceXMLWrapper
Imports System
Imports System.IO

Module Program
    Sub Main()
        Dim html As String = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>"
        File.WriteAllText("temp.html", html)

        Dim prince As New Prince("C:\Program Files\Prince\engine\bin\prince.exe")
        prince.Convert("temp.html", "styled-output.pdf")
        Console.WriteLine("Styled PDF created")
    End Sub
End Module
$vbLabelText   $csharpLabel

After (IronPDF):

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        string html = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("styled-output.pdf");
        Console.WriteLine("Styled PDF created");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim html As String = "<html><head><style>body { font-family: Arial; color: blue; }</style></head><body><h1>Hello World</h1></body></html>"

        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs("styled-output.pdf")
        Console.WriteLine("Styled PDF created")
    End Sub
End Class
$vbLabelText   $csharpLabel

此示例突出了一个关键区别:PrinceXML 需要文件输入,因此在转换之前必须创建一个临时文件(File.WriteAllText("temp.html", html))。IronPDF的 RenderHtmlAsPdf() 直接接受 HTML 字符串——没有临时文件,没有清理代码,没有磁盘 I/O 开销。


迁移 CSS 分页媒体

虽然PrinceXML的 CSS 分页媒体支持功能强大,但它会将供应商锁定在 Prince 特定的 CSS 上,而这些 CSS 在其他地方无法使用:

PrinceXML CSS:

@page {
    size: A4;
    margin: 2cm;
    @top-center {
        content: "Document Title";
    }
    @bottom-right {
        content: counter(page);
    }
}

/* Prince-specific extensions */
prince-pdf-page-label: "Chapter " counter(chapter);
prince-pdf-destination: attr(id);

IronPDF C#(等同):

renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56;    // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
    MaxHeight = 40
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 56;    // ~2cm
renderer.RenderingOptions.MarginBottom = 56;
renderer.RenderingOptions.MarginLeft = 56;
renderer.RenderingOptions.MarginRight = 56;

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
    MaxHeight = 40
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.MarginTop = 56    ' ~2cm
renderer.RenderingOptions.MarginBottom = 56
renderer.RenderingOptions.MarginLeft = 56
renderer.RenderingOptions.MarginRight = 56

renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='text-align:center;'>Document Title</div>",
    .MaxHeight = 40
}

renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='text-align:right;'>Page {page} of {total-pages}</div>",
    .MaxHeight = 25
}
$vbLabelText   $csharpLabel

常见的 CSS 迁移问题

问题 1:CSS @页面不起作用

IronPDF 使用 Chromium,对 @page 的支持有限。 将 CSS 规则转换为 RenderingOptions。

问题 2:页面边框缺失

CSS 边距框(@top-center@bottom-right)是 Prince 特有的。 请改用 HtmlHeader/HtmlFooter

问题 3:字符串集/内容无法正常工作

string-set CSS 属性是 Prince 特有的。 使用 <title> 标签中的 {html-title} 占位符:

<title>Chapter 1: Introduction</title>
<title>Chapter 1: Introduction</title>
HTML
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div>{html-title}</div>"
};
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div>{html-title}</div>"
};
$vbLabelText   $csharpLabel

问题 4:计数器(页数)不正确

使用IronPDF的 {total-pages} 占位符代替 CSS 计数器。


性能比较

手术 PrinceXML IronPDF
简单的 HTML ~400ms ~300ms
复杂 CSS ~600ms ~400ms
JavaScript 页面 有限的 ~500ms
大型文档 ~1500ms ~1000ms
并发 (10) ~4000ms ~1500ms
启动开销 ~200ms ~50ms

迁移后的新功能

迁移到IronPDF后,您将获得PrinceXML无法提供的功能:

PDF 合并

var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");
var pdf1 = PdfDocument.FromFile("chapter1.pdf");
var pdf2 = PdfDocument.FromFile("chapter2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("complete_book.pdf");
Dim pdf1 = PdfDocument.FromFile("chapter1.pdf")
Dim pdf2 = PdfDocument.FromFile("chapter2.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("complete_book.pdf")
$vbLabelText   $csharpLabel

水印

pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

数字签名

var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);
Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)
$vbLabelText   $csharpLabel

表格填写

var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");
var pdf = PdfDocument.FromFile("form.pdf");
pdf.Form.GetFieldByName("Name").Value = "John Doe";
pdf.SaveAs("filled_form.pdf");
Dim pdf = PdfDocument.FromFile("form.pdf")
pdf.Form.GetFieldByName("Name").Value = "John Doe"
pdf.SaveAs("filled_form.pdf")
$vbLabelText   $csharpLabel

功能对比摘要

特征 PrinceXML IronPDF
本地 .NET
外部流程 要求
异步支持 手册包装 本地 async/await
CSS 分页媒体 支持 通过 RenderingOptions
CSS 网格
Flexbox
JavaScript 有限的 完整的 ES2024
生成
合并
拆分
编辑
水印 仅限 CSS HTML/CSS + API
数字签名
PDF/A
加密
格式
NuGet 软件包
服务器安装 要求

迁移清单

迁移前

  • 识别所有 Prince 命令行调用
  • 使用的文档 CSS @page 规则
  • 列出 Prince 特有的 CSS 属性(prince-*, string-set
  • 注意任何 PrinceJavaScript函数
  • 识别所使用的PDF功能(加密、元数据)
  • ironpdf.com获取IronPDF许可证密钥

代码更改

  • 删除 PrinceXMLWrapper NuGet 包 安装 IronPdf NuGet 包
  • 更新命名空间导入
  • Prince 实例化替换为 ChromePdfRenderer
  • prince.Convert() 替换为 RenderHtmlFileAsPdf()RenderHtmlAsPdf()
  • 将 setter 方法转换为 RenderingOptions 属性
  • 将 @page CSS 迁移到 RenderingOptions
  • 将边距框替换为 HtmlHeader/HtmlFooter
  • 将 CSS 计数器转换为 {page}/{total-pages} 占位符
  • 移除 HTML 字符串的临时文件处理。
  • 在应用程序启动时添加许可证初始化

后迁移

  • 测试 HTML 文件转换
  • 测试 HTML 字符串转换
  • 测试 URL 转换
  • 核实页面大小是否匹配
  • 核对边距是否匹配
  • 测试页眉和页脚
  • 核对页码
  • 测试加密/安全性
  • 从服务器上移除 Prince 安装
  • 更新部署脚本

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我