IRONSOFTWAREHOME
视频

从Accusoft BarcodeXpress迁移到 IronBarcode

Curtis Chau
Curtis Chau
Updated: 2026年5月3日

这次迁移的大部分工作都是删除。 两键许可系统 — SetSolutionKeySetOEMLicenseKey 用于运行时 — 完全消失。 实际的条码操作(读取图像、将条码写入文件)转换为更短的IronBarcode等效操作。 如果您的代码库中有一个包裹BarcodeXpress的BarcodeService类,那么许可代码通常占据了很大一部分。 迁移后,那个类将缩小。

为什么要从Accusoft BarcodeXpress迁移?

从 BarcodeXpress 迁移的团队报告了以下触发因素:

**评估模式阻碍准确的基准测试:**没有有效的 OEM/运行时密钥,BarcodeXpress 会用字面字符串" UNLICENSED accusoft.com " 标记解码结果,并将同样的标记应用于生成的2D条码。 在真实文档上进行预购买准确性检测会产生这种水印输出,因此您无法验证库在购买之前能否正确读取您的实际扫描类型。

**两键许可增加操作开销:**BarcodeXpress将SDK许可证(SetSolutionName + SetOEMLicenseKey)分离。 CI/CD 流水线、Docker 容器和容器编排器都需要将这两个关键系统作为单独的密钥进行管理。 缺失或无效的运行时密钥会退回到带水印的输出而不是报错,这会创建一个故障模式,如果断言仅检测非空结果则能通过自动测试。

**任何生产部署至少需要五个运行时许可证:**即使是单服务器部署也需要购买至少五个运行时许可证。 无论实际使用量如何,运行一台生产服务器和一台测试服务器的团队至少需要支付十个运行时许可证费用。

**标准版每分钟处理速度上限为 40 页:**标准版将处理速度限制为每分钟 40 页。 按这个速度,处理 10 万份文件大约需要 41 个小时。 要解除上限,需要升级到Professional版,这除了已经购买的运行时许可证之外,还需要支付更高的每个开发人员席位费用。

**不支持原生 PDF:**必须先使用单独的库将 PDF 文件渲染成图像,BarcodeXpress 才能读取它们。 这种外部依赖关系增加了第二个许可成本、转换步骤,以及保存渲染页面图像带来的额外内存压力。

**线程安全需要实例隔离:**BarcodeXpress的reader对象是有状态的,并且不适合并发访问。 并行批处理要求每个线程都有一个完全初始化的BarcodeXpress实例,并且在每个线程上下文中重复完整的两层许可证初始化。

基本问题

BarcodeXpress在读取任何条码之前需要多步初始化、位图加载和BarcodeType[]配置。

using var bitmap = new Bitmap(imagePath);
var barcodeXpress = new BarcodeXpress(".");
barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
barcodeXpress.Licensing.SetOEMLicenseKey("2.0.OEMLicenseStringFromAccusoft...");

barcodeXpress.reader.BarcodeTypes = new[]
{
    BarcodeType.Code128Barcode,
    BarcodeType.DataMatrixBarcode,
    BarcodeType.QRCodeBarcode
};

Result[] results = barcodeXpress.reader.Analyze(bitmap);
var value = results.FirstOrDefault()?.BarcodeValue;

IronBarcode将整个代码块替换为一个静态调用:

var value = BarcodeReader.Read(imagePath).First().Value;

IronBarcode与 Accusoft BarcodeXpress:功能对比

特征Accusoft BarcodeXpressIronBarcode
许可模式SDK 密钥 + OEM/运行时密钥(单独购买)单永久钥匙
最低运行时许可5(即使只有一台服务器)无运行时许可概念
评估模式解码值和生成的 2D 条码标记有 " UNLICENSED accusoft.com "返回全部值; 仅在生成的输出上添加水印
吞吐量限制40 PPM(标准版)任何级别均无限制
格式自动检测手动 — 必须将BarcodeTypes所有支持的格式均自动运行
PDF 支持需要外部库呈现页面到 Bitmaps原生 — BarcodeReader.Read("doc.pdf")
API 风格基于实例; Bitmap 输入; 属性/方法配置静态工厂方法,流畅 API
线程安全每个线程一个实例是必需的。无状态静态方法 — 线程安全
Docker 许可证配置许可证文件挂载点或许可证服务器单个环境变量
CI/CD 密钥SDK 密钥对 + OEM/运行时密钥一个秘密
.NET Framework / .NET Core单独的包:Accusoft.BarcodeXpress.NetAccusoft.BarcodeXpress.NetCore单一IronBarcode包(.NET Framework 4.6.2+、.NET Core 3.1+、.NET 5–8)
Linux/macOS是 (通过 .NetCore 包)是的——Windows x64/x86、Linux x64、macOS x64/ARM
带有徽标的二维码需要手动 GDI+ 叠加AddBrandLogo("logo.png") 内置的
定价切入点$1,960+ SDK + 最少5个运行时许可证749 美元永久版(Lite,1 位开发者)
永久许可非标准配置——请联系销售是的,所有级别

快速入门:Accusoft BarcodeXpress 到IronBarcode 的迁移

步骤 1:替换 NuGet 软件包

dotnet remove package Accusoft.BarcodeXpress.NetCore
dotnet add package IronBarcode
SHELL

步骤 2:更新命名空间

// Remove
using Accusoft.BarcodeXpressSdk;

// Add
using IronBarCode;

步骤 3:初始化许可证

在应用程序启动时在Startup.cs或依赖注入配置中添加许可初始化一次:

// Add once at application startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";

在生产环境中,从环境变量或密钥管理器中读取密钥:

IronBarCode.License.LicenseKey =
    Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE")
    ?? throw new InvalidOperationException("IronBarcode license key not configured");

无需SetOEMLicenseKey,无需每服务器运行时激活。 这就是完整的许可证设置。

代码迁移示例

许可证初始化

BarcodeXpress 方法:

using Accusoft.BarcodeXpressSdk;

public class BarcodeService
{
    private readonly BarcodeXpress _barcodeXpress;

    public BarcodeService()
    {
        // Constructor takes the path containing the Barcode Xpress runtime files.
        _barcodeXpress = new BarcodeXpress(".");

        // SDK license
        _barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
        _barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);

        // OEM/runtime license — separate purchase, minimum 5 licenses required.
        // Without this call, decoded values and generated 2D barcodes are
        // stamped with " UNLICENSED accusoft.com ".
        _barcodeXpress.Licensing.SetOEMLicenseKey(
            "2.0.OEMLicenseStringFromAccusoft...");
    }
}

IronBarcode方法:

using IronBarCode;

// In Program.cs
IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");

// BarcodeService no longer needs a constructor or any license management
public class BarcodeService
{
    // Ready to use — no initialization needed
}

BarcodeXpress 构造函数仅用于管理两种许可证密钥系统和运行时路径。 IronBarcode在应用程序启动时用一行替换它。BarcodeService类根本不需要构造函数。

条形码读取

BarcodeXpress 方法:

using System.Drawing;
using Accusoft.BarcodeXpressSdk;

public string ReadFirstBarcode(string imagePath)
{
    // Analyze takes a System.Drawing.Bitmap; the SDK does not read PDFs directly.
    using var bitmap = new Bitmap(imagePath);

    _barcodeXpress.reader.BarcodeTypes = new[]
    {
        BarcodeType.Code128Barcode,
        BarcodeType.DataMatrixBarcode,
        BarcodeType.QRCodeBarcode
    };

    Result[] results = _barcodeXpress.reader.Analyze(bitmap);

    return results.FirstOrDefault()?.BarcodeValue;
}

IronBarcode方法:

using IronBarCode;

public string ReadFirstBarcode(string imagePath)
{
    var results = BarcodeReader.Read(imagePath);
    return results.First().Value;
}

new Bitmap(...)加载步骤都消失了。IronBarcode自动检测所有支持符号之间的格式并直接接受文件路径。 如果供应商从 Code 128 切换到 DataMatrix, IronBarcode无需任何代码更改即可继续工作。 结果属性名称也改变:BarcodeValue 变为 BarcodeType 变为 Format。 解决方案范围内的查找和替换功能可以处理这两种重命名操作。

从一张图像中读取多个条形码

BarcodeXpress 方法:

using System.Drawing;
using Accusoft.BarcodeXpressSdk;

public IReadOnlyList<string> ReadAllBarcodes(string imagePath)
{
    using var bitmap = new Bitmap(imagePath);
    _barcodeXpress.reader.BarcodeTypes = new[]
    {
        BarcodeType.Code128Barcode,
        BarcodeType.QRCodeBarcode
    };

    Result[] results = _barcodeXpress.reader.Analyze(bitmap);
    return results.Select(r => r.BarcodeValue).ToList();
}

IronBarcode方法:

using IronBarCode;

public IReadOnlyList<string> ReadAllBarcodes(string imagePath)
{
    var options = new BarcodeReaderOptions { ExpectMultipleBarcodes = true };
    var results = BarcodeReader.Read(imagePath, options);
    return results.Select(r => r.Value).ToList();
}

ExpectMultipleBarcodes 告诉IronBarcode在第一次匹配后继续扫描,这对于包含多个不同区域代码的文档很有用。 有关读取选项的更多详细信息,请参阅IronBarcode读取文档

批量处理

BarcodeXpress是基于实例的,其reader对象是有状态的,因此并行批处理需要每个线程一个实例,并且对每个线程重复完整的两层许可证初始化。 IronBarcode的静态方法是无状态的,因此Parallel.ForEach不需要实例管理。

BarcodeXpress 方法:

using System.Collections.Generic;
using System.Drawing;
using Accusoft.BarcodeXpressSdk;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
    var results = new Dictionary<string, string>();

    foreach (var path in imagePaths)
    {
        using var bitmap = new Bitmap(path);
        _barcodeXpress.reader.BarcodeTypes = new[]
        {
            BarcodeType.Code128Barcode,
            BarcodeType.QRCodeBarcode
        };

        Result[] barcodes = _barcodeXpress.reader.Analyze(bitmap);
        if (barcodes.Length > 0)
            results[path] = barcodes[0].BarcodeValue;
    }

    return results;
}

IronBarcode方法:

using IronBarCode;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public Dictionary<string, string> ProcessBatch(string[] imagePaths)
{
    var results = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(imagePaths, file =>
    {
        var r = BarcodeReader.Read(file);
        var first = r.FirstOrDefault();
        if (first != null)
            results[file] = first.Value;
    });

    return new Dictionary<string, string>(results);
}

如果 BarcodeXpress 标准版每分钟 40 页的上限导致您添加了速率限制处理代码(例如,在每 40 页之间休眠、跟踪每分钟计数器或添加延迟),请完全删除该代码。IronBarcode的吞吐量没有上限。

添加 PDF 支持

BarcodeXpress 无法直接从 PDF 文件中读取条形码。 典型的解决方法是添加一个单独的 PDF 渲染库,将每一页渲染成内存中的图像,然后将这些图像逐一传递给条形码阅读器。

BarcodeXpress 方法:

// Requires a separate PDF library (not shown — varies by team choice)
// Pattern: render each PDF page to a Bitmap, then pass it to Analyze.
foreach (Bitmap pageBitmap in pdfRenderer.RenderPages("document.pdf"))
{
    using (pageBitmap)
    {
        _barcodeXpress.reader.BarcodeTypes = Enum.GetValues(typeof(BarcodeType));
        Result[] barcodes = _barcodeXpress.reader.Analyze(pageBitmap);
        // ... collect results
    }
}

IronBarcode方法:

using IronBarCode;

// One call — no rendering step, no external dependency
var results = BarcodeReader.Read("document.pdf");

foreach (var barcode in results)
{
    Console.WriteLine($"Page {barcode.PageNumber}: [{barcode.Format}] {barcode.Value}");
}

如果itext7或任何其他PDF库仅为支持BarcodeXpress读取工作流而添加,则在迁移后可以删除它。 查看 IronBarcode PDF 阅读指南以获取附加选项,包括页面范围选择。

条形码生成

BarcodeXpress 方法:

using System.Drawing;
using Accusoft.BarcodeXpressSdk;

public void GenerateBarcode(string data, string outputPath)
{
    _barcodeXpress.writer.BarcodeType = BarcodeType.Code128Barcode;
    _barcodeXpress.writer.BarcodeValue = data;

    // CreateBitmap returns a System.Drawing.Bitmap; persist via Bitmap.Save.
    using Bitmap bitmap = _barcodeXpress.writer.CreateBitmap();
    bitmap.Save(outputPath);
}

IronBarcode方法:

using IronBarCode;

public void GenerateBarcode(string data, string outputPath)
{
    BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
        .ResizeTo(400, 100)
        .SaveAsPng(outputPath);
}

流畅链取代了属性赋值、Bitmap.Save步骤。要获取作为二进制数据的条码以存储在数据库中或从API返回:

byte[] pngBytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
    .ToPngBinaryData();

二维码生成

BarcodeXpress 方法:

_barcodeXpress.writer.BarcodeType = BarcodeType.QRCodeBarcode;
_barcodeXpress.writer.BarcodeValue = data;

using Bitmap bitmap = _barcodeXpress.writer.CreateBitmap();
bitmap.Save("qr.png");
// Logo overlay required manual GDI+ drawing on the returned Bitmap

IronBarcode方法:

using IronBarCode;
using IronSoftware.Drawing;

// Simple QR
QRCodeWriter.CreateQrCode("https://example.com", 500)
    .SaveAsPng("qr.png");

// With branded logo
QRCodeWriter.CreateQrCode("https://example.com", 500)
    .AddBrandLogo("logo.png")
    .SaveAsPng("qr-branded.png");

// With high error correction (for logo overlays)
QRCodeWriter.CreateQrCode(
    "https://example.com",
    500,
    QRCodeWriter.QrErrorCorrectionLevel.Highest)
    .AddBrandLogo("logo.png")
    .SaveAsPng("qr-branded-high-ecc.png");

// Colored QR code
QRCodeWriter.CreateQrCode("https://example.com", 300)
    .ChangeBarCodeColor(Color.DarkBlue)
    .SaveAsPng("qr-colored.png");

流畅的 API 内置了徽标嵌入、纠错级别和颜色自定义功能。 BarcodeXpress 的这些功能在初始文件写入后需要手动进行 GDI+ 绘图。 有关更多 QR 代码选项,请参阅 QR 代码生成指南

##Accusoft BarcodeXpressAPI 到IronBarcode映射参考

Accusoft BarcodeXpressIronBarcode
new BarcodeXpress(".")静态方法——无需实例
Licensing.SetSolutionName("...")IronBarCode.License.LicenseKey = "key"
Licensing.SetSolutionKey(a, b, c, d)(removed — not needed)
Licensing.SetOEMLicenseKey(string)(removed — no OEM/runtime key concept)
new Bitmap(path) + reader.Analyze(bitmap)BarcodeReader.Read(path)
reader.BarcodeTypes = new[] { BarcodeType.Code128Barcode, ... }(removed — auto-detection handles all formats)
result.BarcodeValueresult.Value
result.BarcodeTyperesult.Format
writer.BarcodeType = BarcodeType.Code128BarcodeBarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128)
writer.BarcodeValue = "data"(first argument to CreateBarcode)
writer.CreateBitmap() + bitmap.Save(path).SaveAsPng(path)
writer.BarcodeType = BarcodeType.QRCodeBarcodeQRCodeWriter.CreateQrCode(data, size)
40 ppm 标准限值任何层级均无吞吐量限制

常见迁移问题和解决方案

问题 1:属性名称编译错误

**BarcodeXpress:**结果对象公开BarcodeValueBarcodeType,在IronBarcode中不存在。

**解决方案:**在构建之前,对整个解决方案运行查找和替换操作:

grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
SHELL

在所有找到的文件中用result.BarcodeType

问题2:孤立的许可证配置调用

BarcodeXpress: SetSolutionKeySetOEMLicenseKey 的调用 — 加上检测到解码输出中的" UNLICENSED accusoft.com "水印的任何自定义断言 — 广泛存在于许多代码库中,作为防止水印输出故障模式的防御措施。

解决方案: 定位并删除所有此类调用位置 —— IronBarcode中没有等效的状态。 许可证密钥要么有效要么无效,如果无效,则试用限制统一适用,而不是单独降低解码值:

grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "UNLICENSED accusoft" --include="*.cs" .
SHELL

所有这些呼叫站点都可以删除。

问题 3:Docker 许可证文件挂载到环境变量

BarcodeXpress: Docker 部署通常使用COPY或卷装指令将BarcodeXpress许可证配置文件安装到容器中的已知路径。

**解决方案:**删除配置文件副本,并替换为环境变量:

# Remove this
COPY accusoft-license.lic /app/license/

# Add this
ENV IRONBARCODE_LICENSE=YOUR-LICENSE-KEY
Text

应用程序启动时:

IronBarCode.License.LicenseKey =
    Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");

在 Kubernetes 中,许可证密钥会成为 pod 规范中的一个秘密引用:

env:
  - name: IRONBARCODE_LICENSE
    valueFrom:
      secretKeyRef:
        name: ironbarcode-secrets
        key: license-key
Text

问题 4:速率限制处理代码

**BarcodeXpress:**在标准版 40-PPM 上限下处理大批量文件的团队通常会添加代码,以便在处理文档组之间进行休眠、跟踪每分钟计数器或引入延迟,以保持在限制范围内。

**解决方案:**移除所有限速代码。 定位方法:

grep -r "40\|PPM\|pagesPerMinute\|minuteStart" --include="*.cs" .
SHELL

IronBarcode没有吞吐量上限——您可以根据自身基础设施支持的速率进行处理。

问题 5:线程安全——实例池移除

BarcodeXpress: 支持并发处理的代码库通常维护一个ThreadLocal<BarcodeXpress>模式来隔离每个线程的有状态读取器。

**解决方案:**完全移除连接池逻辑。 IronBarcode的BarcodeWriter.CreateBarcode是无状态的静态方法。 来自任意数量线程的并发调用不会相互干扰。

##Accusoft BarcodeXpress迁移清单

迁移前任务

在进行任何代码更改之前,请审核代码库,以确定所有 BarcodeXpress 的使用情况:

grep -r "BarcodeXpress" --include="*.cs" .
grep -r "Accusoft" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "reader\.Analyze" --include="*.cs" .
grep -r "writer\.CreateBitmap" --include="*.cs" .
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
grep -r "BarcodeType\." --include="*.cs" .
SHELL
  • 记录在BarcodeTypes赋值中明确列出的条码格式 — 这些都会在IronBarcode中自动检测。
  • 找出所有可以移除的速率限制处理代码
  • 找出所有仅为支持 BarcodeXpress 读取而添加的 PDF 渲染库——这些库也可以移除。
  • 获取您的IronBarcode许可证密钥并将其添加到您的密钥管理器中。

代码更新任务

  1. 从所有Accusoft.BarcodeXpress.NetCore
  2. 向所有需要条码功能的IronBarcode
  3. 在所有文件中用using Accusoft.BarcodeXpressSdk;
  4. 在应用程序启动时添加IronBarCode.License.LicenseKey = ...
  5. 删除所有BarcodeXpress构造函数调用和实例字段
  6. 删除所有SetOEMLicenseKey调用
  7. 删除任何扫描解码输出中" UNLICENSED accusoft.com "水印的自定义断言
  8. new Bitmap(path) + BarcodeReader.Read(path)
  9. 删除所有reader.BarcodeTypes = ...赋值
  10. result.BarcodeValue
  11. result.BarcodeType
  12. writer.CreateBitmap() + bitmap.Save(path)
  13. 移除速率限制节流代码
  14. 如果存在,请移除 PDF 渲染中间代码。
  15. 删除实例池或BarcodeXpress实例的ThreadLocal模式
  16. 从 Dockerfile 和 docker-compose 文件中移除许可证文件挂载
  17. IRONBARCODE_LICENSE环境变量添加到Docker和容器配置中
  18. 更新 Kubernetes 密钥和 Pod 规范
  19. 更新CI/CD管道密钥 — 删除ACCUSOFT_RUNTIME_KEY; 添加IRONBARCODE_LICENSE

迁移后测试

  • 构建解决方案——修复重命名属性后遗留的任何编译错误
  • 对所有条形码读取操作运行单元测试
  • 对所有条形码生成操作运行单元测试
  • 如适用,请使用 PDF 输入进行测试
  • 运行批量处理测试以确认不存在吞吐量限制行为
  • 部署到测试环境并验证许可证密钥是否能从环境变量中正确解析。

迁移到IronBarcode的主要优势

消除两键许可证复杂性:SetOEMLicenseKey设置完全消失。 一个密钥覆盖从开发到生产的每个环境,并且试用模式返回完整的解码值(而不是在每个值上加盖"UNLICENSED accusoft.com"),因此可以在实际文档上进行预购基准测试。

无最低运行时许可证购买要求: BarcodeXpress 要求任何生产部署至少需要五个运行时许可证。 IronBarcode没有运行时许可概念——一个永久密钥即可覆盖其级别内的任何数量的生产部署。

**吞吐量无上限:**标准版 40-PPM 的上限以及任何为保持在上限内而编写的速率限制代码都可以移除。IronBarcode的处理速度取决于底层硬件和网络支持,在任何定价层级上都没有软件限制的处理速度上限。

原生PDF读取:BarcodeReader.Read("document.pdf")直接处理PDF文件,返回带有页码、格式、值和置信度分数的每页结果。 任何仅为支持 BarcodeXpress 而添加的 PDF 渲染库都可以移除,从而减少依赖项和许可成本。

无状态线程安全:BarcodeWriter.CreateBarcode是无状态的静态方法。 实例池、ThreadLocal模式和每线程初始化块都可以删除。 使用Parallel.ForEach的并发处理不需要结构更改,仅需移除线程的变通办法。

简化容器部署: Docker 和 Kubernetes 部署使用单个环境变量进行许可证配置。 许可证文件分发、许可证服务器基础设施和配置文件挂载全部取消。

Curtis Chau
技术作家

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

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户