IRONSOFTWAREHOME
视频

从Dynamsoft条形码阅读器迁移到IronBarcode

Curtis Chau
Curtis Chau
Updated: 2026年8月1日

大多数从Dynamsoft条形码阅读器迁移到IronBarcode的开发者属于以下两类之一:选择Dynamsoft因为其声誉,然后发现以相机为中心的API与其文档处理使用场景不匹配的人,以及那些运行在气隙或Docker环境中而许可证服务器依赖性引起生产事故的人。

如果您属于第一组,则迁移将移除外部 PDF 渲染库、逐页渲染循环和错误代码许可模式。 如果您属于第二组,迁移将从您的Docker或VPC配置中移除InitLicense网络调用、离线许可证内容捆绑包和刷新周期以及出站网络策略。 无论哪种方式,迁移后代码库都会变短。

本指南坦诚地说明了您的损失:如果您的应用处理实时摄像头帧,Dynamsoft的捕获视觉管道是为这种工作负载量身定制的,IronBarcode不是合适的替代品。 本迁移指南适用于服务器端文件处理、文档工作流以及许可证服务器访问存在问题的环境。

步骤 1:交换NuGet包

dotnet remove package Dynamsoft.DotNet.BarcodeReader.Bundle
dotnet add package BarCode
SHELL

如果您的项目中还添加了专门用于 Dynamsoft 的 PDF 渲染库(最常见的是 PdfiumViewer),也可以将其删除:

# Remove if added only for Dynamsoft PDF support
dotnet remove package PdfiumViewer
dotnet remove package PdfiumViewer.Native.x86_64.v8-xfa
SHELL

步骤 2:替换许可证初始化

这是最直接的简化之处。 Dynamsoft模式要求每次启动时都进行错误代码检查和异常处理:

之前 — Dynamsoft:

using Dynamsoft.License;
using Dynamsoft.Core;

// Must run before any barcode operations
int errorCode = LicenseManager.InitLicense("YOUR-DYNAMSOFT-KEY", out string errorMsg);
if (errorCode != (int)EnumErrorCode.EC_OK)
    throw new InvalidOperationException($"License validation failed [{errorCode}]: {errorMsg}");

之后IronBarcode:

// NuGet: dotnet add package BarCode
using IronBarCode;

// Local validation — no network call, no error code
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";

在ASP.NET Core应用中,将此添加到builder.Build()

IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_KEY")
    ?? "YOUR-LICENSE-KEY";

在Docker或Kubernetes环境中,在您的部署清单中设置IRONBARCODE_KEY环境变量。不需要出站网络规则。

步骤 3:替换命名空间导入

在所有源文件中查找并替换:

grep -r "using Dynamsoft\." --include="*.cs" .
SHELL

替换所有出现的项:

// Before
using Dynamsoft.CVR;
using Dynamsoft.DBR;
using Dynamsoft.License;
using Dynamsoft.Core;

// After
using IronBarCode;

代码迁移示例

基本文件读取

最基本的操作——从图像文件中读取条形码。

之前 — Dynamsoft:

using Dynamsoft.CVR;
using Dynamsoft.DBR;

public string ReadBarcodeFromFile(CaptureVisionRouter router, string imagePath)
{
    CapturedResult result = router.Capture(imagePath, PresetTemplate.PT_READ_BARCODES);
    BarcodeResultItem[] items = result.GetDecodedBarcodesResult()?.GetItems();
    if (items == null || items.Length == 0)
        return null;

    return items[0].GetText();
}

之后IronBarcode:

// NuGet: dotnet add package BarCode
using IronBarCode;

public string ReadBarcodeFromFile(string imagePath)
{
    var results = BarcodeReader.Read(imagePath);
    return results?.FirstOrDefault()?.Value;
}

路由器实例消失了。 BarcodeReader.Read是静态的。 .Value。 使用LINQ对results的空检查更简洁。

读取多个条形码

之前 — Dynamsoft:

using Dynamsoft.CVR;
using Dynamsoft.DBR;

public List<string> ReadAllBarcodes(CaptureVisionRouter router, string imagePath)
{
    SimplifiedCaptureVisionSettings settings = router.GetSimplifiedSettings(
        PresetTemplate.PT_READ_BARCODES);
    settings.BarcodeSettings.ExpectedBarcodesCount = 0; // 0 = find all
    router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings);

    CapturedResult result = router.Capture(imagePath, PresetTemplate.PT_READ_BARCODES);
    BarcodeResultItem[] items = result.GetDecodedBarcodesResult()?.GetItems();
    var values = new List<string>();

    if (items != null)
    {
        foreach (var item in items)
            values.Add(item.GetText());
    }

    return values;
}

之后IronBarcode:

using IronBarCode;

public List<string> ReadAllBarcodes(string imagePath)
{
    var options = new BarcodeReaderOptions
    {
        ExpectMultipleBarcodes = true,
        MaxParallelThreads = 4
    };

    return BarcodeReader.Read(imagePath, options)
        .Select(r => r.Value)
        .ToList();
}

从字节(内存映像)读取

之前 — Dynamsoft:

using Dynamsoft.CVR;
using Dynamsoft.Core;
using Dynamsoft.DBR;

// Requires width, height, stride, and pixel format — low-level buffer API
public string ReadFromBuffer(CaptureVisionRouter router, byte[] rawPixels, int width, int height)
{
    var imageData = new ImageData
    {
        Bytes = rawPixels,
        Width = width,
        Height = height,
        Stride = width * 3, // assuming 24bpp RGB
        Format = EnumImagePixelFormat.IPF_RGB_888
    };

    CapturedResult result = router.Capture(imageData, PresetTemplate.PT_READ_BARCODES);
    return result.GetDecodedBarcodesResult()?.GetItems()?.FirstOrDefault()?.GetText();
}

之后IronBarcode:

using IronBarCode;

// Pass PNG/JPEG/BMP bytes directly — no pixel format or stride calculation
public string ReadFromImageBytes(byte[] imageBytes)
{
    return BarcodeReader.Read(imageBytes)?.FirstOrDefault()?.Value;
}

如果您的应用程序之前已将图像字节转换为 Dynamsoft 的原始像素缓冲区,则您可以将原始编码图像字节(PNG、JPEG、BMP)直接传递给IronBarcode,而无需先解码为原始像素。

PDF条形码读取——移除渲染循环

这通常是迁移过程中代码量减少最多的部分。 移除整个 PdfiumViewer 渲染循环,并用单个调用代替。

之前 — Dynamsoft 与 PdfiumViewer:

// Requires: Dynamsoft.DotNet.BarcodeReader.Bundle + PdfiumViewer + PdfiumViewer.Native.*
using Dynamsoft.CVR;
using Dynamsoft.DBR;
using PdfiumViewer;
using System.Drawing.Imaging;

public List<string> ReadBarcodesFromPdf(CaptureVisionRouter router, string pdfPath)
{
    var allBarcodes = new List<string>();

    using (var pdfDoc = PdfDocument.Load(pdfPath))
    {
        for (int page = 0; page < pdfDoc.PageCount; page++)
        {
            using var image = pdfDoc.Render(page, 300, 300, true);
            using var ms = new MemoryStream();
            image.Save(ms, ImageFormat.Png);

            CapturedResult result = router.Capture(ms.ToArray(),
                PresetTemplate.PT_READ_BARCODES);
            var items = result.GetDecodedBarcodesResult()?.GetItems();
            if (items != null)
            {
                foreach (var item in items)
                    allBarcodes.Add(item.GetText());
            }
        }
    }

    return allBarcodes;
}

之后IronBarcode:

using IronBarCode;

public List<string> ReadBarcodesFromPdf(string pdfPath)
{
    return BarcodeReader.Read(pdfPath)
        .Select(r => r.Value)
        .ToList();
}

页面循环、PdfDocument、300 DPI渲染步骤、MemoryStream以及每页捕获调用全部消失。 IronBarcode在内部处理 PDF 页面。

如果您需要读取带有选项的 PDF 文件(例如,用于读取密集或难以识别的条形码):

using IronBarCode;

public List<string> ReadBarcodesFromPdfAccurate(string pdfPath)
{
    var options = new BarcodeReaderOptions
    {
        Speed = ReadingSpeed.Balanced,
        ExpectMultipleBarcodes = true
    };

    return BarcodeReader.Read(pdfPath, options)
        .Select(r => r.Value)
        .ToList();
}

离线/物理隔离部署

如果您的代码中包含离线许可模式,请将其完全删除:

之前 — Dynamsoft 离线许可证:

using Dynamsoft.License;
using Dynamsoft.Core;

// Dynamsoft offline: fetch license bundle on a connected machine, persist it,
// then replay it on the offline machine via InitLicenseFromLicenseContent.
int errorCode = LicenseManager.InitLicenseFromLicenseContent(
    licenseContent,
    out string errorMsg);

if (errorCode != (int)EnumErrorCode.EC_OK)
    throw new InvalidOperationException($"Offline license failed: {errorMsg}");

之后IronBarcode:

// Remove all of the above. Replace with:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";

没有许可证内容包需要获取和刷新。 没有连接机器引导步骤。密钥在本地验证。

Docker 配置

如果您之前有网络出口规则或代理配置以允许出站HTTPS到Dynamsoft的许可证端点:

# Before: Docker or Kubernetes egress policy
# Required: Allow outbound HTTPS to Dynamsoft licence endpoints

# After: Remove that egress rule.
# IronBarcode does not require outbound network access for license validation.

# Set license via environment variable
env:
  - name: IRONBARCODE_KEY
    valueFrom:
      secretKeyRef:
        name: ironbarcode-license
        key: key
Text

实例管理清理

Dynamsoft使用一个基于CaptureVisionRouter构建的实例API。 如果您的代码在服务类、字段初始化程序或DI注册中创建路由器实例,这些全部消失。

之前——Dynamsoft实例管理:

using Dynamsoft.CVR;
using Dynamsoft.DBR;
using Dynamsoft.License;
using Dynamsoft.Core;

public class BarcodeService : IDisposable
{
    private readonly CaptureVisionRouter _router;

    public BarcodeService()
    {
        int errorCode = LicenseManager.InitLicense("KEY", out string errorMsg);
        if (errorCode != (int)EnumErrorCode.EC_OK)
            throw new InvalidOperationException(errorMsg);

        _router = new CaptureVisionRouter();

        var settings = _router.GetSimplifiedSettings(PresetTemplate.PT_READ_BARCODES);
        settings.BarcodeSettings.ExpectedBarcodesCount = 0;
        _router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings);
    }

    public string[] ReadFile(string path)
    {
        CapturedResult result = _router.Capture(path, PresetTemplate.PT_READ_BARCODES);
        var items = result.GetDecodedBarcodesResult()?.GetItems();
        return items?.Select(i => i.GetText()).ToArray() ?? Array.Empty<string>();
    }

    public void Dispose()
    {
        _router?.Dispose();
    }
}

之后IronBarcode静态API:

// NuGet: dotnet add package BarCode
using IronBarCode;

public class BarcodeService
{
    // No constructor initialization — license set once at app startup
    // No Dispose — no instance to clean up

    public string[] ReadFile(string path)
    {
        var options = new BarcodeReaderOptions { ExpectMultipleBarcodes = true };
        return BarcodeReader.Read(path, options)
            .Select(r => r.Value)
            .ToArray();
    }
}

该类失去了它的构造函数,它的_router字段。 如果此服务在DI中注册为singleton或scoped service来管理路由器生命周期,该注册可以简化或服务可以成为一组静态方法。

阅读速度与超时时间的关系

Dynamsoft使用一个以毫秒为单位的Timeout,针对摄像头帧率进行了优化。 IronBarcode使用一个ReadingSpeed枚举:

Dynamsoft 设置IronBarcode等效产品
settings.Timeout = 100 (摄像头管线)Speed = ReadingSpeed.Faster
低超时时间(优先考虑速度)Speed = ReadingSpeed.Balanced
更高的超时时间(优先考虑准确性)Speed = ReadingSpeed.Detailed
最高精度,无时间压力Speed = ReadingSpeed.ExtremeDetail

对于大多数文档处理工作流中,吞吐量比小于100毫秒的响应时间更重要,ReadingSpeed.Balanced是正确的默认设置:

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};

常见迁移问题

BarcodeResultItem.GetText() vs result.Value

访问器从方法改为属性:

// Before
string value = item.GetText();

// After
string value = result.Value;

BarcodeResultItem.GetFormatString() vs result.Format

Dynamsoft通过GetFormatString()以字符串形式返回格式。 IronBarcode通过result.Format上公开它:

// Before
if (item.GetFormatString() == "QR_CODE")
    Console.WriteLine("Found QR code");

// After
if (result.Format == BarcodeEncoding.QRCode)
    Console.WriteLine("Found QR code");

// For logging without enum comparison — .ToString() works on both
Console.WriteLine($"Format: {result.Format}");

空结果与空集合

当未找到条形码时,Dynamsoft的null。 IronBarcode返回一个空集合。 更新空值检查:

// Before: null check required
CapturedResult result = router.Capture(path, PresetTemplate.PT_READ_BARCODES);
var items = result.GetDecodedBarcodesResult()?.GetItems();
if (items != null && items.Length > 0)
    Process(items[0].GetText());

// After: null-safe but also correct to check Count
var results = BarcodeReader.Read(path);
if (results.Any())
    Process(results.First().Value);

SimplifiedCaptureVisionSettings to BarcodeReaderOptions

GetSimplifiedSettings / Read

// Before
var settings = router.GetSimplifiedSettings(PresetTemplate.PT_READ_BARCODES);
settings.BarcodeSettings.ExpectedBarcodesCount = 0;
settings.Timeout = 500;
router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings);
var result = router.Capture(path, PresetTemplate.PT_READ_BARCODES);

// After
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read(path, options);

迁移清单

运行以下搜索,查找所有需要更新的 Dynamsoft 参考资料:

grep -r "using Dynamsoft\." --include="*.cs" .
grep -r "LicenseManager.InitLicense\|EnumErrorCode\|EC_OK" --include="*.cs" .
grep -r "new CaptureVisionRouter\|router\.Capture\|PresetTemplate" --include="*.cs" .
grep -r "BarcodeResultItem\|GetDecodedBarcodesResult\|GetFormatString" --include="*.cs" .
grep -r "GetSimplifiedSettings\|UpdateSettings\|SimplifiedCaptureVisionSettings" --include="*.cs" .
grep -r "router\.Dispose\|InitLicenseFromLicenseContent" --include="*.cs" .
SHELL

逐场比赛进行分析:

  • using Dynamsoft.*using IronBarCode
  • LicenseManager.InitLicense(key, out errorMsg) + 错误检查 → IronBarCode.License.LicenseKey = "key"
  • new CaptureVisionRouter() → 移除(静态API,无实例)
  • router.Capture(path, PresetTemplate.PT_READ_BARCODES)BarcodeReader.Read(path)
  • router.Capture(imageData, ...) (原始像素缓冲) → BarcodeReader.Read(imageBytes)
  • 每页PDF渲染循环 + router.Capture(pageBytes, ...)BarcodeReader.Read(pdfPath)
  • BarcodeResultItem.GetText()result.Value
  • BarcodeResultItem.GetFormatString()result.Format
  • GetSimplifiedSettings(...) + UpdateSettings(...)new BarcodeReaderOptions { ... }
  • router.Dispose() → 移除
  • LicenseManager.InitLicenseFromLicenseContent(...) → 完全移除
  • 如果添加 PdfiumViewer NuGet包仅仅是为了支持 Dynamsoft PDF 处理,则将其移除。
  • 移除Dynamsoft许可端点的Docker/Kubernetes网络出口规则
  • 在部署配置中设置IRONBARCODE_KEY环境变量
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 天试用密钥
无需信用卡或创建账户