Cómo Personalizar y Agregar Logos a Códigos QR en C#
Migrating from Accusoft BarcodeXpressto IronBarcode
La mayor parte del trabajo en esta migración consiste en eliminar archivos. El sistema de licenciamiento de dos claves — SetSolutionName, SetSolutionKey, y SetOEMLicenseKey para tiempo de ejecución — desaparece por completo. Las operaciones reales de código de barras (leer una imagen, escribir un código de barras en un archivo) se traducen a equivalentes más cortos en IronBarcode. Si tu base de código tiene una clase BarcodeService que envuelve BarcodeXpress, el código de licencia suele ser una gran parte de ella. Después de la migración, esa clase se reduce.
¿Por qué migrar desde Accusoft BarcodeXpress?
Los equipos que migran desde BarcodeXpress informan de los siguientes factores desencadenantes:
El Modo de Evaluación Bloquea Mediciones Precisas: Sin una clave OEM/vigente válida, BarcodeXpress estampa los resultados decodificados con la cadena literal " UNLICENSED accusoft.com " y aplica la misma estampa a los códigos de barras 2D generados. Las pruebas de precisión previas a la compra en documentos reales producen esta salida con marca de agua, por lo que no puedes verificar que la biblioteca lee correctamente los tipos de escaneos antes de comprometerte con una compra.
El licenciamiento de dos claves aumenta la sobrecarga operativa: BarcodeXpress separa la licencia SDK (SetSolutionName + SetSolutionKey) de la licencia OEM/tiempo de ejecución (SetOEMLicenseKey). Las canalizaciones de CI/CD, los contenedores Docker y los orquestadores de contenedores necesitan que ambos sistemas clave se gestionen como secretos separados. Una clave vigente faltante o inválida retrocede a una salida con marca de agua en lugar de generar un error, creando un modo de fallo que puede pasar pruebas automatizadas si las aserciones verifican solo resultados no nulos.
Mínimo cinco licencias de ejecución para cualquier implementación en producción: Incluso una implementación en un solo servidor requiere la compra de al menos cinco licencias de ejecución. Los equipos que gestionan un servidor de producción y un servidor de pruebas pagan un mínimo de diez licencias de ejecución, independientemente del uso real.
Límite de 40 PPM en la edición estándar: La edición estándar limita el procesamiento a 40 páginas por minuto. Procesar un lote de 100.000 documentos lleva aproximadamente 41 horas a ese ritmo. Para eliminar el límite máximo es necesario actualizar a la Edición Professional , que conlleva un coste adicional por puesto de desarrollador, además de las licencias de ejecución ya adquiridas.
Sin compatibilidad nativa con PDF: Los archivos PDF deben convertirse a imágenes mediante una biblioteca independiente antes de que BarcodeXpress pueda leerlos. Esa dependencia externa añade un segundo coste de licencia, un paso de conversión y una presión adicional sobre la memoria debido al almacenamiento de las imágenes de página renderizadas.
La seguridad de los hilos requiere el aislamiento de instancias: El objeto reader de BarcodeXpress es con estado y no es seguro para acceso concurrente. El procesamiento por lotes en paralelo requiere una instancia completamente inicializada de BarcodeXpress por hilo, con la inicialización completa de la licencia de dos capas repetida en cada contexto de hilo.
El problema fundamental
BarcodeXpress requiere una inicialización de varios pasos, una carga de Bitmap y una configuración de BarcodeType[] antes de que cualquier código de barras pueda ser leído:
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
IronBarcode reemplaza todo este bloque con una única llamada estática:
var value = BarcodeReader.Read(imagePath).First().Value;
var value = BarcodeReader.Read(imagePath).First().Value;
Dim value = BarcodeReader.Read(imagePath).First().Value
IronBarcode vs Accusoft BarcodeXpress: Comparación de características
| Característica | Accusoft BarcodeXpress | IronBarcode |
|---|---|---|
| Modelo de licencia | Clave SDK + clave OEM/vigente (compras separadas) | Llave perpetua única |
| Licencias de tiempo de ejecución mínimas | 5 (incluso para 1 servidor) | No existe el concepto de licencia de tiempo de ejecución. |
| Modo de evaluación | Valores decodificados y códigos de barras 2D generados estampados con " UNLICENSED accusoft.com " | Se devolvieron los valores completos; marca de agua sólo en el resultado generado |
| límite de rendimiento | 40 ppm (Edición estándar) | Sin límite en ningún nivel |
| Detección automática de formato | Manual — se debe asignar un arreglo BarcodeType[] a BarcodeTypes |
Automático en todos los formatos compatibles. |
| Compatibilidad con PDF | Requiere biblioteca externa para renderizar páginas a Bitmaps | Nativa — BarcodeReader.Read("doc.pdf") |
| Estilo API | Basado en instancias; entrada de Bitmap; configuración de propiedad/método | Métodos de fábrica estáticos, API fluida |
| Seguridad de los hilos | Se requiere una instancia por hilo. | Métodos estáticos sin estado — a prueba de hilos |
| Configuración de licencia de Docker | Montaje del archivo de licencia o servidor de licencias | Variable de entorno única |
| Se requieren credenciales de CI/CD | Par de claves SDK + clave OEM/vigente | Un secreto |
| .NET Framework / .NET Core | Paquetes separados: Accusoft.BarcodeXpress.Net y Accusoft.BarcodeXpress.NetCore |
Un solo paquete IronBarcode (.NET Framework 4.6.2+, .NET Core 3.1+, .NET 5–8) |
| Linux/macOS | Sí (a través del paquete .NetCore) | Sí — Windows x64/x86, Linux x64, macOS x64/ARM |
| Código QR con logotipo | Se requiere superposición manual de GDI+ | AddBrandLogo("logo.png") incorporado |
| Punto de entrada de precios | $1,960+ SDK + mínimo 5 licencias vigentes | $749 perpetuo (Lite, 1 desarrollador) |
| Licencia perpetua | No es estándar; contacte con ventas. | Sí, todos los niveles |
Inicio rápido: Migración de Accusoft BarcodeXpressa IronBarcode
Paso 1: Sustituir el paquete NuGet
dotnet remove package Accusoft.BarcodeXpress.NetCore
dotnet add package IronBarcode
dotnet remove package Accusoft.BarcodeXpress.NetCore
dotnet add package IronBarcode
Paso 2: Actualizar los espacios de nombres
// Remove
using Accusoft.BarcodeXpressSdk;
// Add
using IronBarCode;
// Remove
using Accusoft.BarcodeXpressSdk;
// Add
using IronBarCode;
Imports IronBarCode
Paso 3: Inicializar licencia
Agrega la inicialización de la licencia una vez al inicio de la aplicación en Program.cs, Startup.cs, o tu configuración de inyección de dependencias:
// 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"
En producción, lea la clave desde una variable de entorno o su gestor de secretos:
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"))
No SetSolutionKey, no SetOEMLicenseKey, sin activación por servidor para tiempo de ejecución. Esa es la configuración completa de la licencia.
Ejemplos de migración de código
Inicialización de licencia
Enfoque de BarcodeXpress:
using Accusoft.BarcodeXpressSdk;
public class BarcodeService
{
private readonly BarcodeXpress _barcodeXpress;
public BarcodeService()
{
// Constructor takes the path containing the Barcode Xpress runtime files.
_barcodeXpress = new BarcodeXpress(".");
// SDK license
_barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
_barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
// OEM/runtime license — separate purchase, minimum 5 licenses required.
// Without this call, decoded values and generated 2D barcodes are
// stamped with " UNLICENSED accusoft.com ".
_barcodeXpress.Licensing.SetOEMLicenseKey(
"2.0.OEMLicenseStringFromAccusoft...");
}
}
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
Enfoque de IronBarcode :
using IronBarCode;
// In Program.cs
IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");
// BarcodeService no longer needs a constructor or any license management
public class BarcodeService
{
// Ready to use — no initialization needed
}
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
El constructor de BarcodeXpress existe únicamente para gestionar dos sistemas de claves de licencia y la ruta de tiempo de ejecución. IronBarcode lo reemplaza con una línea al inicio de la aplicación. La clase BarcodeService no requiere constructor alguno.
Lectura de códigos de barras
Enfoque de BarcodeXpress:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public string ReadFirstBarcode(string imagePath)
{
// Analyze takes a System.Drawing.Bitmap; the SDK does not read PDFs directly.
using var bitmap = new Bitmap(imagePath);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.DataMatrixBarcode,
BarcodeType.QRCodeBarcode
};
Result[] results = _barcodeXpress.reader.Analyze(bitmap);
return results.FirstOrDefault()?.BarcodeValue;
}
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
Enfoque de IronBarcode :
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
El filtro de arreglo BarcodeTypes y el paso de carga new Bitmap(...) ambos desaparecen. IronBarcode detecta automáticamente el formato de entre todas las simbologías soportadas y acepta una ruta de archivo directamente. Si un proveedor cambia del código 128 a DataMatrix, IronBarcode seguirá funcionando sin necesidad de modificar ningún código. Los nombres de las propiedades de resultado también cambian: BarcodeValue se convierte en Value, y BarcodeType se convierte en Format. Una función de búsqueda y reemplazo a nivel de toda la solución gestiona ambos cambios de nombre.
Lectura de múltiples códigos de barras a partir de una sola imagen.
Enfoque de BarcodeXpress:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public IReadOnlyList<string> ReadAllBarcodes(string imagePath)
{
using var bitmap = new Bitmap(imagePath);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.QRCodeBarcode
};
Result[] results = _barcodeXpress.reader.Analyze(bitmap);
return results.Select(r => r.BarcodeValue).ToList();
}
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
Enfoque de IronBarcode :
using IronBarCode;
public IReadOnlyList<string> ReadAllBarcodes(string imagePath)
{
var options = new BarcodeReaderOptions { ExpectMultipleBarcodes = true };
var results = BarcodeReader.Read(imagePath, options);
return results.Select(r => r.Value).ToList();
}
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
ExpectMultipleBarcodes le dice a IronBarcode que continúe escaneando después del primer hallazgo, lo cual es útil para documentos con varios códigos en diferentes regiones. Para obtener más detalles sobre las opciones de lectura, consulte la documentación de lectura de IronBarcode .
Procesamiento por lotes
BarcodeXpress se basa en instancias y su objeto reader es con estado, así que el procesamiento por lotes en paralelo requiere una instancia por hilo con la inicialización completa de la licencia de dos capas repetida por hilo. Los métodos estáticos de IronBarcode son sin estado, por lo que Parallel.ForEach no necesita gestión de instancias.
Enfoque de BarcodeXpress:
using System.Collections.Generic;
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
var results = new Dictionary<string, string>();
foreach (var path in imagePaths)
{
using var bitmap = new Bitmap(path);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.QRCodeBarcode
};
Result[] barcodes = _barcodeXpress.reader.Analyze(bitmap);
if (barcodes.Length > 0)
results[path] = barcodes[0].BarcodeValue;
}
return results;
}
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
Enfoque de IronBarcode :
using IronBarCode;
using System.Collections.Concurrent;
using System.Threading.Tasks;
public Dictionary<string, string> ProcessBatch(string[] imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, file =>
{
var r = BarcodeReader.Read(file);
var first = r.FirstOrDefault();
if (first != null)
results[file] = first.Value;
});
return new Dictionary<string, string>(results);
}
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
Si el límite de 40 páginas por minuto de la edición estándar de BarcodeXpress le obligó a añadir código para gestionar el límite de velocidad (pausas entre grupos de 40, seguimiento de un contador por minuto o adición de retrasos), elimine ese código por completo. IronBarcode no tiene límite de rendimiento.
Agregar compatibilidad con PDF
BarcodeXpress no lee códigos de barras directamente de archivos PDF. La solución habitual consiste en añadir una biblioteca de renderizado de PDF independiente, renderizar cada página en una imagen en memoria y, a continuación, pasar esas imágenes al lector de códigos de barras una por una.
Enfoque de BarcodeXpress:
// Requires a separate PDF library (not shown — varies by team choice)
// Pattern: render each PDF page to a Bitmap, then pass it to Analyze.
foreach (Bitmap pageBitmap in pdfRenderer.RenderPages("document.pdf"))
{
using (pageBitmap)
{
_barcodeXpress.reader.BarcodeTypes = Enum.GetValues(typeof(BarcodeType));
Result[] barcodes = _barcodeXpress.reader.Analyze(pageBitmap);
// ... collect results
}
}
// 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
Enfoque de IronBarcode :
using IronBarCode;
// One call — no rendering step, no external dependency
var results = BarcodeReader.Read("document.pdf");
foreach (var barcode in results)
{
Console.WriteLine($"Page {barcode.PageNumber}: [{barcode.Format}] {barcode.Value}");
}
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
Si Aspose.PDF, PdfiumViewer, itext7, o cualquier otra biblioteca de PDF se agregó únicamente para soportar el flujo de trabajo de lectura de BarcodeXpress, puede ser eliminada después de la migración. Consulta la guía de lectura de PDF de IronBarcode para obtener opciones adicionales, incluida la selección de rango de páginas.
Generación de códigos de barras
Enfoque de BarcodeXpress:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public void GenerateBarcode(string data, string outputPath)
{
_barcodeXpress.writer.BarcodeType = BarcodeType.Code128Barcode;
_barcodeXpress.writer.BarcodeValue = data;
// CreateBitmap returns a System.Drawing.Bitmap; persist via Bitmap.Save.
using Bitmap bitmap = _barcodeXpress.writer.CreateBitmap();
bitmap.Save(outputPath);
}
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
Enfoque de IronBarcode :
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
La cadena fluida reemplaza las asignaciones de propiedades, la llamada CreateBitmap y el paso Bitmap.Save. Para obtener el código de barras como datos binarios para almacenar en una base de datos o devolver desde una 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()
Generación de códigos QR
Enfoque de BarcodeXpress:
_barcodeXpress.writer.BarcodeType = BarcodeType.QRCodeBarcode;
_barcodeXpress.writer.BarcodeValue = data;
using Bitmap bitmap = _barcodeXpress.writer.CreateBitmap();
bitmap.Save("qr.png");
// Logo overlay required manual GDI+ drawing on the returned Bitmap
_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
Enfoque de IronBarcode :
using IronBarCode;
using IronSoftware.Drawing;
// Simple QR
QRCodeWriter.CreateQrCode("https://example.com", 500)
.SaveAsPng("qr.png");
// With branded logo
QRCodeWriter.CreateQrCode("https://example.com", 500)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded.png");
// With high error correction (for logo overlays)
QRCodeWriter.CreateQrCode(
"https://example.com",
500,
QRCodeWriter.QrErrorCorrectionLevel.Highest)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded-high-ecc.png");
// Colored QR code
QRCodeWriter.CreateQrCode("https://example.com", 300)
.ChangeBarCodeColor(Color.DarkBlue)
.SaveAsPng("qr-colored.png");
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")
La incrustación de logotipos, el nivel de corrección de errores y la personalización del color están integrados en la API fluida. BarcodeXpress requiere el dibujo manual con GDI+ después de la escritura inicial del archivo para cualquiera de estas funciones. Para más opciones de códigos QR, consulta la guía de generación de códigos QR.
Referencia de mapeo de la API de Accusoft BarcodeXpressa IronBarcode
| Accusoft BarcodeXpress | IronBarcode |
|---|---|
new BarcodeXpress(".") |
Métodos estáticos: no se requiere instancia. |
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) |
| Límite estándar de 40 ppm | Sin límite de rendimiento en ningún nivel. |
Problemas comunes de migración y soluciones
Problema 1: Errores de compilación en el nombre de la propiedad
BarcodeXpress: Los objetos de resultado exponen BarcodeValue y BarcodeType, que no existen en IronBarcode.
Solución: Ejecute una búsqueda y reemplazo en toda la solución antes de compilarla:
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
Reemplaza result.BarcodeValue con result.Value y result.BarcodeType con result.Format en todos los archivos encontrados.
Problema 2: Llamadas de Configuración de Licencia Huérfanas
BarcodeXpress: Las llamadas SetSolutionName, SetSolutionKey, y SetOEMLicenseKey — además de cualquier aserción personalizada que detecta la marca de agua 'UNLICENSED accusoft.com' en la salida decodificada — existen en muchas bases de código como defensas contra el modo de fallo de salida marcada.
Solución: Localiza y elimina todos esos sitios de llamadas — IronBarcode no tiene un estado equivalente. La clave de licencia es válida o no, y si no lo es, los límites de prueba se aplican de manera uniforme en lugar de degradar valores individuales decodificados:
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" .
Todos estos sitios de llamadas se pueden eliminar.
Problema 3: Montaje del archivo de licencia de Docker en una variable de entorno
BarcodeXpress: Las implementaciones en Docker típicamente montan un archivo de configuración de licencia de BarcodeXpress en el contenedor en una ruta conocida utilizando una instrucción de COPY o de montaje de volumen.
Solución: Elimine la copia del archivo de configuración y reemplácela con una variable de entorno:
# Remove this
COPY accusoft-license.lic /app/license/
# Add this
ENV IRONBARCODE_LICENSE=YOUR-LICENSE-KEY
Al iniciar la aplicación:
IronBarCode.License.LicenseKey =
Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");
IronBarCode.License.LicenseKey =
Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");
Imports System
IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE")
En Kubernetes, la clave de licencia se convierte en una referencia secreta en la especificación del pod:
env:
- name: IRONBARCODE_LICENSE
valueFrom:
secretKeyRef:
name: ironbarcode-secrets
key: license-key
env:
- name: IRONBARCODE_LICENSE
valueFrom:
secretKeyRef:
name: ironbarcode-secrets
key: license-key
Problema 4: Código de gestión de límites de velocidad
BarcodeXpress: Los equipos que procesan grandes lotes por debajo del límite de 40 ppm de la edición estándar a menudo agregan código para pausar el procesamiento entre grupos de documentos, realizar un seguimiento de los contadores por minuto o introducir retrasos para mantenerse dentro del límite.
Solución: Eliminar todo el código de limitación de velocidad. Localízalo con:
grep -r "40\|PPM\|pagesPerMinute\|minuteStart" --include="*.cs" .
grep -r "40\|PPM\|pagesPerMinute\|minuteStart" --include="*.cs" .
IronBarcode no tiene límite de rendimiento: procesa a la velocidad que admita tu infraestructura.
Problema 5: Seguridad de subprocesos: eliminación del grupo de instancias
BarcodeXpress: Las bases de código que soportan procesamiento concurrente a menudo mantienen un pool de instancias de BarcodeXpress o usan un patrón ThreadLocal<BarcodeXpress> para aislar el lector con estado por hilo.
Solución: Eliminar por completo la lógica de agrupación de recursos. Los BarcodeReader.Read y BarcodeWriter.CreateBarcode de IronBarcode son métodos estáticos sin estado. Las llamadas simultáneas desde cualquier número de hilos no interfieren entre sí.
Lista de verificación de migración de Accusoft BarcodeXpress
Tareas previas a la migración
Antes de realizar cualquier cambio en el código, revise la base de código para identificar todos los usos de BarcodeXpress:
grep -r "BarcodeXpress" --include="*.cs" .
grep -r "Accusoft" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "reader\.Analyze" --include="*.cs" .
grep -r "writer\.CreateBitmap" --include="*.cs" .
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
grep -r "BarcodeType\." --include="*.cs" .
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" .
- Toma nota de qué formatos de código de barras están listados explícitamente en asignaciones de
BarcodeTypes— todos estos se vuelven autodetectados en IronBarcode - Identificar cualquier código de gestión de límites de velocidad que se pueda eliminar.
- Identifique cualquier biblioteca de renderizado de PDF agregada únicamente para admitir la lectura de BarcodeXpress; estas también se pueden eliminar.
- Obtén tu clave de licencia de IronBarcode y añádela a tu gestor de secretos.
Tareas de actualización de código
- Eliminar
Accusoft.BarcodeXpress.NetCorede todos los archivos.csproj - Agregar
IronBarcodea todos los archivos.csprojque necesitan funcionalidad de código de barras - Reemplazar
using Accusoft.BarcodeXpressSdk;conusing IronBarCode;en todos los archivos - Agregar
IronBarCode.License.LicenseKey = ...al inicio de la aplicación - Eliminar todas las llamadas de constructor
BarcodeXpressy campos de instancia - Eliminar todas las llamadas
SetSolutionName,SetSolutionKey, ySetOEMLicenseKey - Elimina cualquier aserción personalizada que escanee la salida decodificada para la marca de agua " UNLICENSED accusoft.com "
- Reemplazar
new Bitmap(path)+reader.Analyze(bitmap)conBarcodeReader.Read(path) - Eliminar todas las asignaciones
reader.BarcodeTypes = ... - Reemplazar
result.BarcodeValueconresult.Value - Reemplazar
result.BarcodeTypeconresult.Format - Reemplazar
writer.CreateBitmap()+bitmap.Save(path)conBarcodeWriter.CreateBarcode(data, encoding).SaveAsPng(path) - Eliminar el código de limitación de velocidad
- Elimine el código intermedio de renderizado de PDF, si está presente.
- Eliminar el agrupamiento de instancias o patrones
ThreadLocalpara instancias de BarcodeXpress - Elimine los puntos de montaje de archivos de licencia de los archivos Dockerfile y docker-compose.
- Agregar la variable de entorno
IRONBARCODE_LICENSEa las configuraciones de Docker y del contenedor - Actualizar los secretos de Kubernetes y las especificaciones de los pods.
- Actualizar los secretos del pipeline de CI/CD — eliminar
ACCUSOFT_SOLUTION_KEYyACCUSOFT_RUNTIME_KEY; agregarIRONBARCODE_LICENSE
Pruebas posteriores a la migración
- Construir la solución: corregir cualquier error de compilación restante de las propiedades renombradas.
- Ejecutar pruebas unitarias en todas las operaciones de lectura de códigos de barras.
- Ejecutar pruebas unitarias en todas las operaciones de generación de códigos de barras.
- Pruebe con archivos PDF de entrada si corresponde.
- Ejecutar una prueba de procesamiento por lotes para confirmar que no hay comportamiento de limitación del rendimiento.
- Implementar en un entorno de prueba y verificar que la clave de licencia se resuelva correctamente desde la variable de entorno.
Principales ventajas de migrar a IronBarcode
Eliminación de la Complejidad de Licencia de Dos Claves: La configuración de SetSolutionName, SetSolutionKey, y SetOEMLicenseKey desaparece por completo. Una clave cubre cada entorno desde el desarrollo hasta la producción, y el modo de prueba devuelve valores decodificados completos (en lugar de estampar cada uno con "UNLICENSED accusoft.com") para que las pruebas de rendimiento previas a la compra en documentos reales sean posibles.
Sin compra mínima de licencia de ejecución: BarcodeXpress requiere un mínimo de cinco licencias de ejecución para cualquier implementación en producción. IronBarcode no tiene un concepto de licencia de tiempo de ejecución: la clave perpetua única cubre cualquier número de implementaciones de producción dentro de su nivel.
Rendimiento sin límite: Se puede eliminar el límite de 40 ppm de la edición estándar y cualquier código de limitación de velocidad escrito para mantenerse dentro de ese rango. IronBarcode procesa las solicitudes a la velocidad que permita el hardware y la red subyacentes, sin ningún límite impuesto por el software en ningún nivel de precios.
Lectura Nativa de PDF: BarcodeReader.Read("document.pdf") procesa archivos PDF directamente, devolviendo resultados por página con número de página, formato, valor y puntaje de confianza. Cualquier biblioteca de renderizado de PDF añadida únicamente para dar soporte a BarcodeXpress puede eliminarse, reduciendo así las dependencias y los costes de licencia.
Seguridad en Hilos sin Estado: BarcodeReader.Read y BarcodeWriter.CreateBarcode son métodos estáticos sin estado. Los pools de instancias, los patrones ThreadLocal, y los bloques de inicialización por hilo pueden ser eliminados. El procesamiento concurrente con Parallel.ForEach no requiere cambios estructurales más allá de eliminar los métodos alternativos para manejo de hilos.
Despliegue de contenedores simplificado: Los despliegues de Docker y Kubernetes utilizan una única variable de entorno para la configuración de la licencia. Se eliminan la distribución de archivos de licencia, la infraestructura del servidor de licencias y el montaje de archivos de configuración.
Preguntas Frecuentes
¿Por qué debería migrar de Accusoft BarcodeXpress a IronBarcode?
Entre las razones más comunes se incluyen la simplificación de licencias (eliminando la complejidad de SDK + clave de tiempo de ejecución), la eliminación de límites de rendimiento, la obtención de compatibilidad nativa con PDF, la mejora de la implementación de Docker/CI/CD y la reducción de la repetición de API en el código de producción.
¿Cómo reemplazo las llamadas a la API de Accusoft BarcodeXpress con IronBarcode?
Sustituya la creación de instancias y la repetición de licencias por IronBarCode.License.LicenseKey = "key". Sustituya las llamadas al lector por BarcodeReader.Read(path) y las llamadas al escritor por BarcodeWriter.CreateBarcode(data, encoding). Los métodos estáticos no requieren gestión de instancias.
¿Cuánto código cambia al migrar de Accusoft BarcodeXpress a IronBarcode?
La mayoría de las migraciones se traducen en menos líneas de código. Se eliminan la repetición de licencias, los constructores de instancias y la configuración explícita de formatos. Las operaciones básicas de lectura/escritura se traducen a equivalentes IronBarcode más cortos con objetos de resultado más limpios.
¿Necesito mantener tanto Accusoft BarcodeXpress como IronBarcode instalados durante la migración?
No. La mayoría de las migraciones son sustituciones directas en lugar de operaciones paralelas. Migre una clase de servicio cada vez, sustituya la referencia NuGet y actualice los patrones de instanciación y llamada a la API antes de pasar a la siguiente clase.
¿Cuál es el nombre del paquete NuGet para IronBarcode?
El paquete es 'IronBarCode' (con B y C mayúsculas). Instálalo con 'Install-Package IronBarCode' o 'dotnet add package IronBarCode'. La directiva using en el código es 'using IronBarCode;'.
¿Cómo simplifica IronBarcode el despliegue de Docker en comparación con Accusoft BarcodeXpress?
IronBarcode es un paquete NuGet sin archivos SDK externos ni configuración de licencia montada. En Docker, establezca la variable de entorno IRONBARCODE_LICENSE_KEY y el paquete se encargará de la validación de la licencia al inicio.
¿IronBarcode detecta automáticamente todos los formatos de código de barras después de migrar desde Accusoft BarcodeXpress?
Sí, IronBarcode detecta automáticamente la simbología de todos los formatos compatibles. No es necesaria la enumeración explícita de BarcodeTypes. Si ya se conoce el formato y el rendimiento es importante, BarcodeReaderOptions permite restringir el espacio de búsqueda como optimización.
¿Puede IronBarcode leer códigos de barras de PDF sin una biblioteca independiente?
Sí. BarcodeReader.Read("document.pdf") procesa archivos PDF de forma nativa. Los resultados incluyen PageNumber, Format, Value y Confidence para cada código de barras encontrado. No es necesario ningún paso externo de procesamiento de PDF.
¿Cómo gestiona IronBarcode el procesamiento paralelo de códigos de barras?
Los métodos estáticos de IronBarcode no tienen estado y son seguros para los hilos. Utilice Parallel.ForEach directamente sobre listas de archivos sin gestión de instancias por subproceso. BarcodeReaderOptions.MaxParallelThreads controla el presupuesto interno de hilos.
¿Qué propiedades de los resultados cambian al migrar de Accusoft BarcodeXpress a IronBarcode?
Cambios de nombre comunes: BarcodeValue se convierte en Value, BarcodeType se convierte en Format. Los resultados de IronBarcode también añaden Confidence y PageNumber. Una búsqueda y sustitución en toda la solución gestiona los cambios de nombre en el código de procesamiento de resultados existente.
¿Cómo configuro las licencias de IronBarcode en un proceso CI/CD?
Almacene IRONBARCODE_LICENSE_KEY como un secreto de canalización y asigne IronBarCode.License.LicenseKey en el código de inicio de la aplicación. Un secreto cubre todos los entornos, incluidos los de desarrollo, prueba, montaje y producción.
¿Admite IronBarcode la generación de códigos QR con estilos personalizados?
Sí. QRCodeWriter.CreateQrCode() admite colores personalizados mediante ChangeBarCodeColor(), incrustación de logotipos mediante AddBrandLogo(), niveles de corrección de errores configurables y múltiples formatos de salida, incluidos PNG, JPG, PDF y stream.

