Skip to footer content
MIGRATION GUIDES

Migrating from Accusoft BarcodeXpress to IronBarcode

Most of the work in this migration is deletion. The two-key licensing system — SetSolutionName, SetSolutionKey, and SetOEMLicenseKey for runtime — disappears entirely. The actual barcode operations (read an image, write a barcode to a file) translate to shorter IronBarcode equivalents. If your codebase has a BarcodeService class that wraps BarcodeXpress, the licensing code is often a large fraction of it. After migration, that class shrinks.

Why Migrate from Accusoft BarcodeXpress

Teams migrating from BarcodeXpress report these triggers:

Evaluation Mode Blocks Accurate Benchmarking: Without a valid OEM/runtime key, BarcodeXpress stamps decoded results with the literal string " UNLICENSED accusoft.com " and applies the same stamp to generated 2D barcodes. Pre-purchase accuracy testing on real documents produces this watermarked output, so you cannot verify that the library reads your actual scan types correctly before committing to a purchase.

Two-Key Licensing Increases Operational Overhead: BarcodeXpress separates the SDK license (SetSolutionName + SetSolutionKey) from the OEM/runtime license (SetOEMLicenseKey). CI/CD pipelines, Docker containers, and container orchestrators each need both key systems managed as separate secrets. A missing or invalid runtime key falls back to watermarked output rather than raising an error, creating a failure mode that can pass automated tests if assertions check only for non-null results.

Minimum Five Runtime Licenses for Any Production Deployment: Even a single-server deployment requires purchasing at least five runtime licenses. Teams running one production server and one staging server pay for ten runtime licenses minimum, regardless of actual usage.

40 PPM Standard Edition Ceiling: The Standard Edition throttles processing to 40 pages per minute. A batch of 100,000 documents takes roughly 41 hours at that rate. Removing the ceiling requires upgrading to the Professional Edition, which carries a higher per-developer seat cost on top of the runtime licenses already purchased.

No Native PDF Support: PDF files must be rendered to images using a separate library before BarcodeXpress can read them. That external dependency adds a second licensing cost, a conversion step, and additional memory pressure from holding rendered page images.

Thread Safety Requires Instance Isolation: BarcodeXpress's reader object is stateful and not safe for concurrent access. Parallel batch processing requires one fully initialized BarcodeXpress instance per thread, with the full two-layer license initialization repeated in each thread context.

The Fundamental Problem

BarcodeXpress requires a multi-step initialization, a Bitmap load, and a BarcodeType[] configuration before any barcode can be read:

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;
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;
Imports System.Drawing
Imports Accusoft.BarcodeXpressSdk

Using bitmap As New Bitmap(imagePath)
    Dim 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() {
        BarcodeType.Code128Barcode,
        BarcodeType.DataMatrixBarcode,
        BarcodeType.QRCodeBarcode
    }

    Dim results As Result() = barcodeXpress.Reader.Analyze(bitmap)
    Dim value = results.FirstOrDefault()?.BarcodeValue
End Using
$vbLabelText   $csharpLabel

IronBarcode replaces this entire block with a single static call:

var value = BarcodeReader.Read(imagePath).First().Value;
var value = BarcodeReader.Read(imagePath).First().Value;
Dim value = BarcodeReader.Read(imagePath).First().Value
$vbLabelText   $csharpLabel

IronBarcode vs Accusoft BarcodeXpress: Feature Comparison

Feature Accusoft BarcodeXpress IronBarcode
License model SDK key + OEM/runtime key (separate purchases) Single perpetual key
Minimum runtime licenses 5 (even for 1 server) No runtime license concept
Evaluation mode Decoded values and generated 2D barcodes stamped with " UNLICENSED accusoft.com " Full values returned; watermark on generated output only
Throughput limit 40 PPM (Standard Edition) No limit at any tier
Format auto-detection Manual — must assign a BarcodeType[] array to BarcodeTypes Automatic across all supported formats
PDF support Requires external library to render pages to Bitmaps Native — BarcodeReader.Read("doc.pdf")
API style Instance-based; Bitmap input; property/method configuration Static factory methods, fluent API
Thread safety Instance-per-thread required Stateless static methods — thread-safe
Docker license config License file mount or license server Single environment variable
CI/CD secrets required SDK key pair + OEM/runtime key One secret
.NET Framework / .NET Core Separate packages: Accusoft.BarcodeXpress.Net and Accusoft.BarcodeXpress.NetCore Single IronBarcode package (.NET Framework 4.6.2+, .NET Core 3.1+, .NET 5–8)
Linux/macOS Yes (via .NetCore package) Yes — Windows x64/x86, Linux x64, macOS x64/ARM
QR code with logo Manual GDI+ overlay required AddBrandLogo("logo.png") built in
Pricing entry point $1,960+ SDK + minimum 5 runtime licenses $749 perpetual (Lite, 1 developer)
Perpetual license Not standard — contact sales Yes, all tiers

Quick Start: Accusoft BarcodeXpress to IronBarcode Migration

Step 1: Replace NuGet Package

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

Step 2: Update Namespaces

// Remove
using Accusoft.BarcodeXpressSdk;

// Add
using IronBarCode;
// Remove
using Accusoft.BarcodeXpressSdk;

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

Step 3: Initialize License

Add license initialization once at application startup in Program.cs, Startup.cs, or your dependency injection configuration:

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

In production, read the key from an environment variable or your secrets manager:

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

License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE"), Throw New InvalidOperationException("IronBarcode license key not configured"))
$vbLabelText   $csharpLabel

No SetSolutionKey, no SetOEMLicenseKey, no per-server runtime activation. That is the complete license setup.

Code Migration Examples

License Initialization

BarcodeXpress Approach:

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...");
    }
}
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...");
    }
}
Imports Accusoft.BarcodeXpressSdk

Public Class BarcodeService
    Private ReadOnly _barcodeXpress As BarcodeXpress

    Public Sub New()
        ' 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...")
    End Sub
End Class
$vbLabelText   $csharpLabel

IronBarcode Approach:

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
}
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
}
Imports IronBarCode

' In Program.vb
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
End Class
$vbLabelText   $csharpLabel

The BarcodeXpress constructor exists solely to manage two license key systems and the runtime path. IronBarcode replaces it with one line at application startup. The BarcodeService class requires no constructor at all.

Barcode Reading

BarcodeXpress Approach:

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;
}
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;
}
Imports System.Drawing
Imports Accusoft.BarcodeXpressSdk

Public Function ReadFirstBarcode(imagePath As String) As String
    ' Analyze takes a System.Drawing.Bitmap; the SDK does not read PDFs directly.
    Using bitmap As New Bitmap(imagePath)
        _barcodeXpress.reader.BarcodeTypes = New BarcodeType() {
            BarcodeType.Code128Barcode,
            BarcodeType.DataMatrixBarcode,
            BarcodeType.QRCodeBarcode
        }

        Dim results As Result() = _barcodeXpress.reader.Analyze(bitmap)

        Return results.FirstOrDefault()?.BarcodeValue
    End Using
End Function
$vbLabelText   $csharpLabel

IronBarcode Approach:

using IronBarCode;

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

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

Public Function ReadFirstBarcode(imagePath As String) As String
    Dim results = BarcodeReader.Read(imagePath)
    Return results.First().Value
End Function
$vbLabelText   $csharpLabel

The BarcodeTypes array filter and the new Bitmap(...) load step both disappear. IronBarcode auto-detects format across all supported symbologies and accepts a file path directly. If a supplier switches from Code 128 to DataMatrix, IronBarcode continues to work without any code change. Result property names also change: BarcodeValue becomes Value, and BarcodeType becomes Format. A solution-wide search-and-replace handles both renames.

Reading Multiple Barcodes from One Image

BarcodeXpress Approach:

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();
}
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();
}
Imports System.Drawing
Imports Accusoft.BarcodeXpressSdk

Public Function ReadAllBarcodes(imagePath As String) As IReadOnlyList(Of String)
    Using bitmap As New Bitmap(imagePath)
        _barcodeXpress.reader.BarcodeTypes = New BarcodeType() {
            BarcodeType.Code128Barcode,
            BarcodeType.QRCodeBarcode
        }

        Dim results As Result() = _barcodeXpress.reader.Analyze(bitmap)
        Return results.Select(Function(r) r.BarcodeValue).ToList()
    End Using
End Function
$vbLabelText   $csharpLabel

IronBarcode Approach:

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

Public Function ReadAllBarcodes(imagePath As String) As IReadOnlyList(Of String)
    Dim options As New BarcodeReaderOptions With {.ExpectMultipleBarcodes = True}
    Dim results = BarcodeReader.Read(imagePath, options)
    Return results.Select(Function(r) r.Value).ToList()
End Function
$vbLabelText   $csharpLabel

ExpectMultipleBarcodes tells IronBarcode to continue scanning after the first match, which is useful for documents with several codes in different regions. For more detail on reading options, see the IronBarcode reading documentation.

Batch Processing

BarcodeXpress is instance-based and its reader object is stateful, so parallel batch processing requires one instance per thread with the full two-layer license initialization repeated per thread. IronBarcode's static methods are stateless, so Parallel.ForEach needs no instance management.

BarcodeXpress Approach:

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;
}
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;
}
Imports System.Collections.Generic
Imports System.Drawing
Imports Accusoft.BarcodeXpressSdk

Public Function ProcessBatch(imagePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim results As New Dictionary(Of String, String)()

    For Each path In imagePaths
        Using bitmap As New Bitmap(path)
            _barcodeXpress.reader.BarcodeTypes = New BarcodeType() {
                BarcodeType.Code128Barcode,
                BarcodeType.QRCodeBarcode
            }

            Dim barcodes As Result() = _barcodeXpress.reader.Analyze(bitmap)
            If barcodes.Length > 0 Then
                results(path) = barcodes(0).BarcodeValue
            End If
        End Using
    Next

    Return results
End Function
$vbLabelText   $csharpLabel

IronBarcode Approach:

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);
}
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);
}
Imports IronBarCode
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

Public Function ProcessBatch(imagePaths As String()) As Dictionary(Of String, String)
    Dim results = New ConcurrentDictionary(Of String, String)()

    Parallel.ForEach(imagePaths, Sub(file)
        Dim r = BarcodeReader.Read(file)
        Dim first = r.FirstOrDefault()
        If first IsNot Nothing Then
            results(file) = first.Value
        End If
    End Sub)

    Return New Dictionary(Of String, String)(results)
End Function
$vbLabelText   $csharpLabel

If the BarcodeXpress Standard Edition's 40-pages-per-minute ceiling caused you to add rate-limit handling code — sleeping between groups of 40, tracking a per-minute counter, or adding delays — remove that code entirely. IronBarcode has no throughput ceiling.

Adding PDF Support

BarcodeXpress does not read barcodes directly from PDF files. The typical workaround involves adding a separate PDF rendering library, rendering each page to an image in memory, and then passing those images to the barcode reader one at a time.

BarcodeXpress Approach:

// 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
    }
}
// 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
    }
}
Imports System
Imports System.Drawing

' Requires a separate PDF library (not shown — varies by team choice)
' Pattern: render each PDF page to a Bitmap, then pass it to Analyze.
For Each pageBitmap As Bitmap In pdfRenderer.RenderPages("document.pdf")
    Using pageBitmap
        _barcodeXpress.reader.BarcodeTypes = [Enum].GetValues(GetType(BarcodeType))
        Dim barcodes As Result() = _barcodeXpress.reader.Analyze(pageBitmap)
        ' ... collect results
    End Using
Next
$vbLabelText   $csharpLabel

IronBarcode Approach:

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

' One call — no rendering step, no external dependency
Dim results = BarcodeReader.Read("document.pdf")

For Each barcode In results
    Console.WriteLine($"Page {barcode.PageNumber}: [{barcode.Format}] {barcode.Value}")
Next
$vbLabelText   $csharpLabel

If Aspose.PDF, PdfiumViewer, itext7, or any other PDF library was added solely to support the BarcodeXpress reading workflow, it can be removed after migration. See the IronBarcode PDF reading guide for additional options including page range selection.

Barcode Generation

BarcodeXpress Approach:

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);
}
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);
}
Imports System.Drawing
Imports Accusoft.BarcodeXpressSdk

Public Sub GenerateBarcode(data As String, outputPath As String)
    _barcodeXpress.writer.BarcodeType = BarcodeType.Code128Barcode
    _barcodeXpress.writer.BarcodeValue = data

    ' CreateBitmap returns a System.Drawing.Bitmap; persist via Bitmap.Save.
    Using bitmap As Bitmap = _barcodeXpress.writer.CreateBitmap()
        bitmap.Save(outputPath)
    End Using
End Sub
$vbLabelText   $csharpLabel

IronBarcode Approach:

using IronBarCode;

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

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

Public Sub GenerateBarcode(data As String, outputPath As String)
    BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
        .ResizeTo(400, 100) _
        .SaveAsPng(outputPath)
End Sub
$vbLabelText   $csharpLabel

The fluent chain replaces the property assignments, the CreateBitmap call, and the Bitmap.Save step. To get the barcode as binary data for storing in a database or returning from an API:

byte[] pngBytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
    .ToPngBinaryData();
byte[] pngBytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
    .ToPngBinaryData();
Dim pngBytes As Byte() = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128).ToPngBinaryData()
$vbLabelText   $csharpLabel

QR Code Generation

BarcodeXpress Approach:

_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
_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
Imports System.Drawing

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

Using bitmap As Bitmap = _barcodeXpress.writer.CreateBitmap()
    bitmap.Save("qr.png")
    ' Logo overlay required manual GDI+ drawing on the returned Bitmap
End Using
$vbLabelText   $csharpLabel

IronBarcode Approach:

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");
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");
Imports IronBarCode
Imports 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")
$vbLabelText   $csharpLabel

Logo embedding, error correction level, and color customization are all built into the fluent API. BarcodeXpress requires manual GDI+ drawing after the initial file write for any of these features. For more QR code options, see the QR code generation guide.

Accusoft BarcodeXpress API to IronBarcode Mapping Reference

Accusoft BarcodeXpress IronBarcode
new BarcodeXpress(".") Static methods — no instance required
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.BarcodeValue result.Value
result.BarcodeType result.Format
writer.BarcodeType = BarcodeType.Code128Barcode BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128)
writer.BarcodeValue = "data" (first argument to CreateBarcode)
writer.CreateBitmap() + bitmap.Save(path) .SaveAsPng(path)
writer.BarcodeType = BarcodeType.QRCodeBarcode QRCodeWriter.CreateQrCode(data, size)
40 PPM Standard limit No throughput limit at any tier

Common Migration Issues and Solutions

Issue 1: Property Name Compile Errors

BarcodeXpress: Result objects expose BarcodeValue and BarcodeType, which do not exist in IronBarcode.

Solution: Run search-and-replace across the solution before building:

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

Replace result.BarcodeValue with result.Value and result.BarcodeType with result.Format throughout all files found.

Issue 2: Orphaned License Configuration Calls

BarcodeXpress: SetSolutionName, SetSolutionKey, and SetOEMLicenseKey calls — plus any custom assertions that detect the " UNLICENSED accusoft.com " watermark in decoded output — exist across many codebases as defenses against the watermarked-output failure mode.

Solution: Locate and delete all such call sites — IronBarcode has no equivalent state. The license key is either valid or not, and if it is not, the trial limits apply uniformly rather than degrading individual decoded values:

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

All of these call sites can be deleted.

Issue 3: Docker License File Mount to Environment Variable

BarcodeXpress: Docker deployments typically mount a BarcodeXpress license configuration file into the container at a known path using a COPY or volume mount instruction.

Solution: Remove the config file copy and replace with an environment variable:

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

# Add this
ENV IRONBARCODE_LICENSE=YOUR-LICENSE-KEY

In application startup:

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

IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE")
$vbLabelText   $csharpLabel

In Kubernetes, the license key becomes a secret reference in the pod spec:

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

Issue 4: Rate Limit Handling Code

BarcodeXpress: Teams processing large batches under the Standard Edition 40-PPM ceiling often added code to sleep between groups of documents, track per-minute counters, or introduce delays to stay within the limit.

Solution: Remove all rate-limiting code. Locate it with:

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

IronBarcode has no throughput ceiling — process at whatever rate your infrastructure supports.

Issue 5: Thread Safety — Instance Pool Removal

BarcodeXpress: Codebases that support concurrent processing often maintain a pool of BarcodeXpress instances or use a ThreadLocal<BarcodeXpress> pattern to isolate the stateful reader per thread.

Solution: Remove the pooling logic entirely. IronBarcode's BarcodeReader.Read and BarcodeWriter.CreateBarcode are stateless static methods. Concurrent calls from any number of threads do not interfere with each other.

Accusoft BarcodeXpress Migration Checklist

Pre-Migration Tasks

Audit the codebase to identify all BarcodeXpress usage before making any code changes:

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" .
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
  • Note which barcode formats are explicitly listed in BarcodeTypes assignments — these all become auto-detected in IronBarcode
  • Identify any rate-limit handling code that can be removed
  • Identify any PDF rendering libraries added solely to support BarcodeXpress reading — these can also be removed
  • Obtain your IronBarcode license key and add it to your secrets manager

Code Update Tasks

  1. Remove Accusoft.BarcodeXpress.NetCore from all .csproj files
  2. Add IronBarcode to all .csproj files that need barcode functionality
  3. Replace using Accusoft.BarcodeXpressSdk; with using IronBarCode; across all files
  4. Add IronBarCode.License.LicenseKey = ... to application startup
  5. Delete all BarcodeXpress constructor calls and instance fields
  6. Delete all SetSolutionName, SetSolutionKey, and SetOEMLicenseKey calls
  7. Delete any custom assertions that scan decoded output for the " UNLICENSED accusoft.com " watermark
  8. Replace new Bitmap(path) + reader.Analyze(bitmap) with BarcodeReader.Read(path)
  9. Remove all reader.BarcodeTypes = ... assignments
  10. Replace result.BarcodeValue with result.Value
  11. Replace result.BarcodeType with result.Format
  12. Replace writer.CreateBitmap() + bitmap.Save(path) with BarcodeWriter.CreateBarcode(data, encoding).SaveAsPng(path)
  13. Remove rate-limit throttling code
  14. Remove PDF rendering intermediary code if present
  15. Remove instance pooling or ThreadLocal patterns for BarcodeXpress instances
  16. Remove license file mounts from Dockerfile and docker-compose files
  17. Add IRONBARCODE_LICENSE environment variable to Docker and container configs
  18. Update Kubernetes secrets and pod specs
  19. Update CI/CD pipeline secrets — remove ACCUSOFT_SOLUTION_KEY and ACCUSOFT_RUNTIME_KEY; add IRONBARCODE_LICENSE

Post-Migration Testing

  • Build the solution — fix any remaining compile errors from renamed properties
  • Run unit tests against all barcode read operations
  • Run unit tests against all barcode generation operations
  • Test with PDF inputs if applicable
  • Run a batch processing test to confirm no throughput throttling behavior
  • Deploy to a staging environment and verify the license key resolves correctly from the environment variable

Key Benefits of Migrating to IronBarcode

Elimination of Two-Key License Complexity: The SetSolutionName, SetSolutionKey, and SetOEMLicenseKey setup disappears entirely. One key covers every environment from development to production, and the trial mode returns complete decoded values (rather than stamping each one with " UNLICENSED accusoft.com ") so pre-purchase benchmarking on real documents is possible.

No Runtime License Minimum Purchase: BarcodeXpress requires a minimum of five runtime licenses for any production deployment. IronBarcode has no runtime license concept — the single perpetual key covers any number of production deployments within its tier.

Throughput Without a Ceiling: The Standard Edition 40-PPM cap and any rate-limiting code written to stay within it can be removed. IronBarcode processes at whatever rate the underlying hardware and network support, with no software-imposed ceiling at any pricing tier.

Native PDF Reading: BarcodeReader.Read("document.pdf") processes PDF files directly, returning per-page results with page number, format, value, and confidence score. Any PDF rendering library added solely to support BarcodeXpress can be removed, reducing dependencies and licensing costs.

Stateless Thread Safety: BarcodeReader.Read and BarcodeWriter.CreateBarcode are stateless static methods. Instance pools, ThreadLocal patterns, and per-thread initialization blocks can all be removed. Concurrent processing with Parallel.ForEach requires no structural changes beyond removing the threading workarounds.

Simplified Container Deployment: Docker and Kubernetes deployments use a single environment variable for license configuration. License file distribution, license server infrastructure, and config file mounts are all eliminated.

Frequently Asked Questions

Why should I migrate from Accusoft BarcodeXpress to IronBarcode?

Common reasons include simplifying licensing (removing SDK + runtime key complexity), eliminating throughput limits, gaining native PDF support, improving Docker/CI/CD deployment, and reducing API boilerplate in production code.

How do I replace Accusoft BarcodeXpress API calls with IronBarcode?

Replace instance creation and licensing boilerplate with IronBarCode.License.LicenseKey = "key". Replace reader calls with BarcodeReader.Read(path) and writer calls with BarcodeWriter.CreateBarcode(data, encoding). Static methods require no instance management.

How much code changes when migrating from Accusoft BarcodeXpress to IronBarcode?

Most migrations result in fewer lines of code. Licensing boilerplate, instance constructors, and explicit format configuration are removed. Core read/write operations map to shorter IronBarcode equivalents with cleaner result objects.

Do I need to keep both Accusoft BarcodeXpress and IronBarcode installed during migration?

No. Most migrations are direct replacements rather than parallel operation. Migrate one service class at a time, replace the NuGet reference, and update the instantiation and API call patterns before moving to the next class.

What is the NuGet package name for IronBarcode?

The package is 'IronBarCode' (with capital B and C). Install it with 'Install-Package IronBarCode' or 'dotnet add package IronBarCode'. The using directive in code is 'using IronBarCode;'.

How does IronBarcode simplify Docker deployment compared to Accusoft BarcodeXpress?

IronBarcode is a NuGet package with no external SDK files or mounted license configuration. In Docker, set the IRONBARCODE_LICENSE_KEY environment variable and the package handles license validation at startup.

Does IronBarcode detect all barcode formats automatically after migrating from Accusoft BarcodeXpress?

Yes. IronBarcode auto-detects symbology across all supported formats. Explicit BarcodeTypes enumeration is not required. If format is already known and performance matters, BarcodeReaderOptions allows restricting the search space as an optimization.

Can IronBarcode read barcodes from PDFs without a separate library?

Yes. BarcodeReader.Read("document.pdf") processes PDF files natively. Results include PageNumber, Format, Value, and Confidence for each barcode found. No external PDF rendering step is required.

How does IronBarcode handle parallel barcode processing?

IronBarcode's static methods are stateless and thread-safe. Use Parallel.ForEach directly over file lists without per-thread instance management. BarcodeReaderOptions.MaxParallelThreads controls the internal thread budget.

What result properties change when migrating from Accusoft BarcodeXpress to IronBarcode?

Common renames: BarcodeValue becomes Value, BarcodeType becomes Format. IronBarcode results also add Confidence and PageNumber. A solution-wide search-and-replace handles the renames in existing result-processing code.

How do I set up IronBarcode licensing in a CI/CD pipeline?

Store IRONBARCODE_LICENSE_KEY as a pipeline secret and assign IronBarCode.License.LicenseKey in application startup code. One secret covers all environments including development, test, staging, and production.

Does IronBarcode support QR code generation with custom styling?

Yes. QRCodeWriter.CreateQrCode() supports custom colors via ChangeBarCodeColor(), logo embedding via AddBrandLogo(), configurable error correction levels, and multiple output formats including PNG, JPG, PDF, and stream.

Jordi Bardia
Software Engineer
Jordi is most proficient in Python, C# and C++, when he isn’t leveraging his skills at Iron Software; he’s game programming. Sharing responsibilities for product testing, product development and research, Jordi adds immense value to continual product improvement. The varied experience keeps him challenged and engaged, and he ...
Read More

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me