Przejdź do treści stopki
FILMY

Jak generować obrazy kodów kreskowych w języku C# dla platformy .NET przy użyciu biblioteki IronBarcode for .NET

Migrating from Dynamsoft Barcode Reader to IronBarcode

Większość deweloperów, którzy dokonują migracji z Dynamsoft Barcode Reader do IronBarcode, należy do jednej z dwóch grup: tych, którzy wybrali Dynamsoft ze względu na jego renomę, a następnie odkryli, że API skoncentrowane na kamerze nie pasowało do przypadku użycia przetwarzania dokumentów, oraz tych, którzy działają w środowiskach zamkniętych lub Docker, gdzie zależność od serwera licencyjnego powodowała incydenty produkcyjne.

Jeśli należysz do pierwszej grupy, migracja usuwa zewnętrzną bibliotekę renderowania PDF, pętlę renderowania na stronę oraz wzorzec licencji oparty na kodach błędów. Jeśli jesteś w drugiej grupie, migracja usuwa wywołanie sieciowe InitLicense, pakiet licencji offline i cykl odświeżania oraz zewnętrzną politykę sieciową z Twojej konfiguracji Docker lub VPC. Tak czy inaczej, po tej migracji kod źródłowy staje się krótszy.

Niniejszy przewodnik szczerze mówi o tym, co tracisz: jeśli Twoja aplikacja przetwarza ramki kamery w czasie rzeczywistym, pipeline Capture Vision Dynamsofta nadaje się najlepiej do tego obciążenia, a IronBarcode nie jest odpowiednim zamiennikiem. Ten przewodnik po migracji dotyczy przetwarzania plików po stronie serwera, przepływów pracy z dokumentami oraz środowisk, w których dostęp do serwera licencji stanowi problem.

Krok 1: Zamień pakiety NuGet

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

Jeśli w projekcie znajduje się również biblioteka do renderowania plików PDF dodana specjalnie dla Dynamsoft (najczęściej jest to PdfiumViewer), można ją również usunąć:

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

Krok 2: Zastąp inicjalizację licencji

To właśnie tutaj następuje najbardziej bezpośrednie uproszczenie. Wzorzec Dynamsoft wymaga sprawdzania kodów błędów i obsługi wyjątków przy każdym uruchomieniu:

Przed — 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}");
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}");
Imports Dynamsoft.License
Imports Dynamsoft.Core

' Must run before any barcode operations
Dim errorCode As Integer = LicenseManager.InitLicense("YOUR-DYNAMSOFT-KEY", errorMsg)
If errorCode <> CType(EnumErrorCode.EC_OK, Integer) Then
    Throw New InvalidOperationException($"License validation failed [{errorCode}]: {errorMsg}")
End If
$vbLabelText   $csharpLabel

Po — IronBarcode:

// NuGet: dotnet add package BarCode
using IronBarCode;

// Local validation — no network call, no error code
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
// NuGet: dotnet add package BarCode
using IronBarCode;

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

' Local validation — no network call, no error code
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

W aplikacji ASP.NET Core dodaj to do Program.cs przed builder.Build():

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

IronBarCode.License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONBARCODE_KEY"), "YOUR-LICENSE-KEY")
$vbLabelText   $csharpLabel

W środowisku Docker lub Kubernetes ustaw zmienną środowiskową IRONBARCODE_KEY w swoim manifeście wdrożenia. Nie są wymagane zewnętrzne reguły sieciowe.

Krok 3: Zastąp importy przestrzeni nazw

Znajdź i zamień we wszystkich plikach źródłowych:

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

Zastąp każde wystąpienie:

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

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

// After
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

Przykłady migracji kodu

Podstawowe odczytywanie plików

Najbardziej podstawowa operacja — odczytanie BARCODE-a z pliku graficznego.

Przed — 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();
}
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();
}
Imports Dynamsoft.CVR
Imports Dynamsoft.DBR

Public Function ReadBarcodeFromFile(router As CaptureVisionRouter, imagePath As String) As String
    Dim result As CapturedResult = router.Capture(imagePath, PresetTemplate.PT_READ_BARCODES)
    Dim items As BarcodeResultItem() = result.GetDecodedBarcodesResult()?.GetItems()
    If items Is Nothing OrElse items.Length = 0 Then
        Return Nothing
    End If

    Return items(0).GetText()
End Function
$vbLabelText   $csharpLabel

Po — IronBarcode:

// NuGet: dotnet add package BarCode
using IronBarCode;

public string ReadBarcodeFromFile(string imagePath)
{
    var results = BarcodeReader.Read(imagePath);
    return results?.FirstOrDefault()?.Value;
}
// NuGet: dotnet add package BarCode
using IronBarCode;

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

Public Function ReadBarcodeFromFile(imagePath As String) As String
    Dim results = BarcodeReader.Read(imagePath)
    Return results?.FirstOrDefault()?.Value
End Function
$vbLabelText   $csharpLabel

Instancja routera zniknęła. BarcodeReader.Read jest statyczna. BarcodeResultItem.GetText() staje się .Value. Sprawdzenie zerowe na results jest czystsze z LINQ.

Odczytywanie wielu BarCodes

Przed — 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;
}
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;
}
Imports Dynamsoft.CVR
Imports Dynamsoft.DBR

Public Function ReadAllBarcodes(router As CaptureVisionRouter, imagePath As String) As List(Of String)
    Dim settings As SimplifiedCaptureVisionSettings = router.GetSimplifiedSettings(PresetTemplate.PT_READ_BARCODES)
    settings.BarcodeSettings.ExpectedBarcodesCount = 0 ' 0 = find all
    router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings)

    Dim result As CapturedResult = router.Capture(imagePath, PresetTemplate.PT_READ_BARCODES)
    Dim items As BarcodeResultItem() = result.GetDecodedBarcodesResult()?.GetItems()
    Dim values As New List(Of String)()

    If items IsNot Nothing Then
        For Each item In items
            values.Add(item.GetText())
        Next
    End If

    Return values
End Function
$vbLabelText   $csharpLabel

Po — 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();
}
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();
}
Imports IronBarCode

Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
    Dim options As New BarcodeReaderOptions With {
        .ExpectMultipleBarcodes = True,
        .MaxParallelThreads = 4
    }

    Return BarcodeReader.Read(imagePath, options) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

Odczytywanie z bajtów (obrazy w pamięci)

Przed — 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();
}
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();
}
Imports Dynamsoft.CVR
Imports Dynamsoft.Core
Imports Dynamsoft.DBR

' Requires width, height, stride, and pixel format — low-level buffer API
Public Function ReadFromBuffer(router As CaptureVisionRouter, rawPixels As Byte(), width As Integer, height As Integer) As String
    Dim imageData As New ImageData With {
        .Bytes = rawPixels,
        .Width = width,
        .Height = height,
        .Stride = width * 3, ' assuming 24bpp RGB
        .Format = EnumImagePixelFormat.IPF_RGB_888
    }

    Dim result As CapturedResult = router.Capture(imageData, PresetTemplate.PT_READ_BARCODES)
    Return result.GetDecodedBarcodesResult()?.GetItems()?.FirstOrDefault()?.GetText()
End Function
$vbLabelText   $csharpLabel

Po — 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;
}
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;
}
Imports IronBarCode

Public Function ReadFromImageBytes(imageBytes As Byte()) As String
    Return BarcodeReader.Read(imageBytes)?.FirstOrDefault()?.Value
End Function
$vbLabelText   $csharpLabel

Jeśli Twoja aplikacja wcześniej konwertowała bajty obrazu na surowy bufor pikseli dla Dynamsoft, możesz przekazać oryginalne zakodowane bajty obrazu (PNG, JPEG, BMP) bezpośrednio do IronBarcode bez konieczności wcześniejszego dekodowania do surowych pikseli.

Odczytywanie BarCode'ów z plików PDF — usunięcie pętli renderowania

Jest to zazwyczaj największa redukcja kodu w ramach migracji. Usuń całą pętlę renderowania PdfiumViewer i zastąp ją pojedynczym wywołaniem.

Przed — Dynamsoft z 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;
}
// 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;
}
Imports Dynamsoft.CVR
Imports Dynamsoft.DBR
Imports PdfiumViewer
Imports System.Drawing.Imaging

Public Function ReadBarcodesFromPdf(router As CaptureVisionRouter, pdfPath As String) As List(Of String)
    Dim allBarcodes As New List(Of String)()

    Using pdfDoc As PdfDocument = PdfDocument.Load(pdfPath)
        For page As Integer = 0 To pdfDoc.PageCount - 1
            Using image = pdfDoc.Render(page, 300, 300, True)
                Using ms As New MemoryStream()
                    image.Save(ms, ImageFormat.Png)

                    Dim result As CapturedResult = router.Capture(ms.ToArray(), PresetTemplate.PT_READ_BARCODES)
                    Dim items = result.GetDecodedBarcodesResult()?.GetItems()
                    If items IsNot Nothing Then
                        For Each item In items
                            allBarcodes.Add(item.GetText())
                        Next
                    End If
                End Using
            End Using
        Next
    End Using

    Return allBarcodes
End Function
$vbLabelText   $csharpLabel

Po — IronBarcode:

using IronBarCode;

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

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

Public Function ReadBarcodesFromPdf(pdfPath As String) As List(Of String)
    Return BarcodeReader.Read(pdfPath) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

Pętla strony, PdfDocument, krok renderowania 300 DPI, MemoryStream i wywołanie Capture na każdej stronie znikają. IronBarcode obsługuje strony PDF wewnętrznie.

Jeśli chcesz odczytać plik PDF z opcjami (dla gęstych lub trudnych BarCodes):

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();
}
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();
}
Imports IronBarCode

Public Function ReadBarcodesFromPdfAccurate(pdfPath As String) As List(Of String)
    Dim options As New BarcodeReaderOptions With {
        .Speed = ReadingSpeed.Balanced,
        .ExpectMultipleBarcodes = True
    }

    Return BarcodeReader.Read(pdfPath, options) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

Wdrożenie offline / w środowisku izolowanym

Jeśli Twój obecny kod zawiera wzorzec licencji offline, usuń go całkowicie:

Przed — Licencja offline 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}");
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}");
Imports Dynamsoft.License
Imports Dynamsoft.Core

' Dynamsoft offline: fetch license bundle on a connected machine, persist it,
' then replay it on the offline machine via InitLicenseFromLicenseContent.
Dim errorMsg As String
Dim errorCode As Integer = LicenseManager.InitLicenseFromLicenseContent(licenseContent, errorMsg)

If errorCode <> CType(EnumErrorCode.EC_OK, Integer) Then
    Throw New InvalidOperationException($"Offline license failed: {errorMsg}")
End If
$vbLabelText   $csharpLabel

Po — IronBarcode:

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

Nie ma wiązki zawartości licencji do pobrania i odświeżenia. Brak kroku uruchamiania połączonego urządzenia. Klucz jest weryfikowany lokalnie.

Konfiguracja Docker

Jeśli wcześniej miałeś zasady wyjścia sieciowego lub konfigurację proxy, aby umożliwić wychodzący HTTPS do punktów licencyjnych 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
# 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
YAML

Porządkowanie zarządzania instancjami

Dynamsoft używa opartego na instancjach API zbudowanego wokół CaptureVisionRouter. Jeśli Twój kod tworzy instancje routera w klasach serwisowych, inicjalizatorach pól lub rejestracjach DI, wszystko to znika:

Przed — Zarządzanie instancjami 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();
    }
}
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();
    }
}
Imports Dynamsoft.CVR
Imports Dynamsoft.DBR
Imports Dynamsoft.License
Imports Dynamsoft.Core

Public Class BarcodeService
    Implements IDisposable

    Private ReadOnly _router As CaptureVisionRouter

    Public Sub New()
        Dim errorCode As Integer = LicenseManager.InitLicense("KEY", errorMsg:=Nothing)
        If errorCode <> CType(EnumErrorCode.EC_OK, Integer) Then
            Throw New InvalidOperationException(errorMsg)
        End If

        _router = New CaptureVisionRouter()

        Dim settings = _router.GetSimplifiedSettings(PresetTemplate.PT_READ_BARCODES)
        settings.BarcodeSettings.ExpectedBarcodesCount = 0
        _router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings)
    End Sub

    Public Function ReadFile(path As String) As String()
        Dim result As CapturedResult = _router.Capture(path, PresetTemplate.PT_READ_BARCODES)
        Dim items = result.GetDecodedBarcodesResult()?.GetItems()
        Return If(items?.Select(Function(i) i.GetText()).ToArray(), Array.Empty(Of String)())
    End Function

    Public Sub Dispose() Implements IDisposable.Dispose
        _router?.Dispose()
    End Sub
End Class
$vbLabelText   $csharpLabel

Po — statyczne API IronBarcode:

// 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();
    }
}
// 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();
    }
}
Imports IronBarCode

Public Class BarcodeService
    ' No constructor initialization — license set once at app startup
    ' No Dispose — no instance to clean up

    Public Function ReadFile(path As String) As String()
        Dim options As New BarcodeReaderOptions With {.ExpectMultipleBarcodes = True}
        Return BarcodeReader.Read(path, options) _
            .Select(Function(r) r.Value) _
            .ToArray()
    End Function
End Class
$vbLabelText   $csharpLabel

Klasa traci swój konstruktor, implementację IDisposable i pole _router. Jeśli usługa ta była zarejestrowana w DI jako usługa singletonowa lub w zakriwie, aby zarządzać cyklem życia routera, taka rejestracja może zostać uproszczona lub usługa może stać się zbiorem statycznych metod.

Mapowanie prędkości czytania a limit czasu

Dynamsoft używa Timeout w milisekundach zoptymalizowanego dla szybkości klatek kamery. IronBarcode używa ReadingSpeed enum:

Ustawienia Dynamsoft Odpowiednik IronBarcode
settings.Timeout = 100 (camera pipeline) Speed = ReadingSpeed.Faster
Krótki limit czasu (priorytet szybkości) Speed = ReadingSpeed.Balanced
Dłuższy limit czasu (priorytet dla dokładności) Speed = ReadingSpeed.Detailed
Maksymalna dokładność, bez presji czasowej Speed = ReadingSpeed.ExtremeDetail

Dla większości przepływów pracy przetwarzania dokumentów, gdzie wydajność jest ważniejsza niż czas odpowiedzi poniżej 100 ms, ReadingSpeed.Balanced to odpowiedni domyślny wybór:

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,
    ExpectMultipleBarcodes = true,
    MaxParallelThreads = 4
};
Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = True,
    .MaxParallelThreads = 4
}
$vbLabelText   $csharpLabel

Typowe problemy związane z migracją

BarcodeResultItem.GetText() vs result.Value

Dostęp zmienia się z metody na właściwość:

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

// After
string value = result.Value;
// Before
string value = item.GetText();

// After
string value = result.Value;
' Before
Dim value As String = item.GetText()

' After
Dim value As String = result.Value
$vbLabelText   $csharpLabel

BarcodeResultItem.GetFormatString() vs result.Format

Dynamsoft zwraca format jako ciąg znaków poprzez GetFormatString(). IronBarcode przedstawia to jako BarcodeEncoding enum na 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}");
// 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}");
' Before
If item.GetFormatString() = "QR_CODE" Then
    Console.WriteLine("Found QR code")
End If

' After
If result.Format = BarcodeEncoding.QRCode Then
    Console.WriteLine("Found QR code")
End If

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

Wyniki zerowe a pusta kolekcja

Dynamsoft's GetDecodedBarcodesResult() może zwrócić null, gdy nie znaleziono żadnych kodów kreskowych. IronBarcode zwraca pustą kolekcję. Zaktualizuj sprawdzanie wartości null:

// 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);
// 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);
Imports System.Linq

' Before: null check required
Dim result As CapturedResult = router.Capture(path, PresetTemplate.PT_READ_BARCODES)
Dim items = result.GetDecodedBarcodesResult()?.GetItems()
If items IsNot Nothing AndAlso items.Length > 0 Then
    Process(items(0).GetText())
End If

' After: null-safe but also correct to check Count
Dim results = BarcodeReader.Read(path)
If results.Any() Then
    Process(results.First().Value)
End If
$vbLabelText   $csharpLabel

SimplifiedCaptureVisionSettings to BarcodeReaderOptions

Wzorzec GetSimplifiedSettings / UpdateSettings staje się BarcodeReaderOptions przekazywany do 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);
// 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);
' Before
Dim settings = router.GetSimplifiedSettings(PresetTemplate.PT_READ_BARCODES)
settings.BarcodeSettings.ExpectedBarcodesCount = 0
settings.Timeout = 500
router.UpdateSettings(PresetTemplate.PT_READ_BARCODES, settings)
Dim result = router.Capture(path, PresetTemplate.PT_READ_BARCODES)

' After
Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,
    .ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read(path, options)
$vbLabelText   $csharpLabel

Lista kontrolna migracji

Uruchom poniższe wyszukiwania, aby znaleźć wszystkie odniesienia do Dynamsoft, które wymagają aktualizacji:

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" .
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

Przejrzyj wszystkie dopasowania:

  • using Dynamsoft.*using IronBarCode
  • LicenseManager.InitLicense(key, out errorMsg) + sprawdzenie błędu → IronBarCode.License.LicenseKey = "key"
  • new CaptureVisionRouter() → usuń (statyczne API, brak instancji)
  • router.Capture(path, PresetTemplate.PT_READ_BARCODES)BarcodeReader.Read(path)
  • router.Capture(imageData, ...) (bufor surowych pikseli) → BarcodeReader.Read(imageBytes)
  • Pętla renderowania PDF na stronę + router.Capture(pageBytes, ...)BarcodeReader.Read(pdfPath)
  • BarcodeResultItem.GetText()result.Value
  • BarcodeResultItem.GetFormatString()result.Format
  • GetSimplifiedSettings(...) + UpdateSettings(...)new BarcodeReaderOptions { ... }
  • router.Dispose() → usuń
  • LicenseManager.InitLicenseFromLicenseContent(...) → usuń całkowicie
  • Usuń pakiety NuGet PdfiumViewer, jeśli zostały dodane wyłącznie w celu obsługi przetwarzania plików PDF przez Dynamsoft
  • Usuń zasady wyjścia sieciowego Docker/Kubernetes dla punktów licencji Dynamsoft
  • Ustaw zmienną środowiskową IRONBARCODE_KEY w konfiguracji wdrożenia

Często Zadawane Pytania

Dlaczego warto przejść z Dynamsoft BarCode Reader na IronBarcode?

Typowe powody to uproszczenie licencjonowania (eliminacja złożoności związanej z SDK i kluczem uruchomieniowym), zniesienie limitów przepustowości, uzyskanie natywnej obsługi plików PDF, usprawnienie wdrażania w środowisku Docker/CI/CD oraz ograniczenie powtarzalnego kodu API w kodzie produkcyjnym.

Jak zastąpić wywołania API Dynamsoft za pomocą IronBarcode?

Zastąp standardowe fragmenty kodu dotyczące tworzenia instancji i licencjonowania wyrażeniem IronBarCode.License.LicenseKey = "key". Zastąp wywołania czytnika wyrażeniem BarcodeReader.Read(path), a wywołania zapisu wyrażeniem BarcodeWriter.CreateBarcode(data, encoding). Metody statyczne nie wymagają zarządzania instancjami.

Jak bardzo zmienia się kod podczas migracji z Dynamsoft BarCode Reader do IronBarcode?

Większość migracji skutkuje zmniejszeniem liczby linii kodu. Usuwane są standardowe fragmenty dotyczące licencji, konstruktory instancji oraz jawna konfiguracja formatów. Podstawowe operacje odczytu/zapisu są mapowane na krótsze odpowiedniki w IronBarcode z bardziej przejrzystymi obiektami wynikowymi.

Czy podczas migracji muszę mieć zainstalowane zarówno Dynamsoft BarCode Reader, jak i IronBarcode?

Nie. Większość migracji polega na bezpośredniej wymianie, a nie na równoległym działaniu. Należy migrować po jednej klasie usługowej na raz, zastąpić odwołanie do NuGet oraz zaktualizować wzorce instancjonowania i wywoływania API przed przejściem do kolejnej klasy.

Jaka jest nazwa pakietu NuGet dla IronBarcode?

Pakiet nosi nazwę „IronBarcode” (z wielkimi literami B i C). Zainstaluj go za pomocą polecenia „Install-Package IronBarcode” lub „dotnet add package IronBarcode”. Dyrektywa using w kodzie to „using IronBarcode;”.

W jaki sposób IronBarcode upraszcza wdrażanie Docker w porównaniu z Dynamsoft BarCode Reader?

IronBarcode to pakiet NuGet bez zewnętrznych plików SDK ani konfiguracji licencji. W Dockerze należy ustawić zmienną środowiskową IRONBARCODE_LICENSE_KEY, a pakiet zajmie się weryfikacją licencji podczas uruchamiania.

Czy IronBarcode automatycznie wykrywa wszystkie formaty BARCODE po migracji z Dynamsoft?

Tak. IronBarcode automatycznie wykrywa symbole we wszystkich obsługiwanych formatach. Wyraźne wyliczenie typów kodów kreskowych nie jest wymagane. Jeśli format jest już znany, a wydajność ma znaczenie, BarcodeReaderOptions pozwala ograniczyć obszar wyszukiwania w celu optymalizacji.

Czy IronBarcode może odczytywać BarCodes z plików PDF bez oddzielnej biblioteki?

Tak. BarCodeReader.Read("document.pdf") przetwarza pliki PDF natywnie. Wyniki obejmują PageNumber, Format, Value i Confidence dla każdego znalezionego kodu kreskowego. Nie jest wymagany żaden zewnętrzny etap renderowania pliku PDF.

W jaki sposób IronBarcode obsługuje równoległe przetwarzanie kodów kreskowych?

Metody statyczne IronBarcode są bezstanowe i bezpieczne dla wątków. Użyj Parallel.ForEach bezpośrednio na listach plików bez zarządzania instancjami dla poszczególnych wątków. BarcodeReaderOptions.MaxParallelThreads kontroluje wewnętrzny limit wątków.

Jakie właściwości wyników ulegają zmianie podczas migracji z Dynamsoft BarCode Reader do IronBarcode?

Typowe zmiany nazw: BarcodeValue staje się Value, BarcodeType staje się Format. Wyniki IronBarcode zawierają również Confidence i PageNumber. Funkcja wyszukiwania i zamiany w całym rozwiązaniu obsługuje zmiany nazw w istniejącym kodzie przetwarzania wyników.

Jak skonfigurować licencjonowanie IronBarcode w potoku CI/CD?

Zapisz IronBarcode_LICENSE_KEY jako sekret potoku i przypisz IronBarCode.License.LicenseKey w kodzie uruchamiającym aplikację. Jeden sekret obejmuje wszystkie środowiska, w tym środowisko programistyczne, testowe, przejściowe i produkcyjne.

Czy IronBarcode obsługuje generowanie kodów QR z niestandardowym stylem?

Tak. Funkcja QRCodeWriter.CreateQrCode() obsługuje niestandardowe kolory za pomocą ChangeBarCodeColor(), osadzanie logo za pomocą AddBrandLogo(), konfigurowalne poziomy korekcji błędów oraz wiele formatów wyjściowych, w tym PNG, JPG, PDF i strumień.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej

Zespół wsparcia Iron

Jesteśmy online 24 godziny, 5 dni w tygodniu.
Czat
E-mail
Zadzwoń do mnie