如何在C#中自定義和新增標志到QR碼
從Accusoft BarcodeXpress遷移至 IronBarcode
這次遷移中的大部分工作是刪除。 雙密鑰授權系統 —— SetSolutionKey 和 SetOEMLicenseKey 用於運行時 —— 全部消失。 實際的條碼操作(讀取影像,在檔案中寫入條碼)轉換為更短的IronBarcode等效操作。 如果您的程式碼庫中有一個 BarcodeService 類別包裹 BarcodeXpress,則授權程式碼常常是其中的一大部分。 遷移後,這個類別縮小了。
為何從Accusoft BarcodeXpress遷移
從 BarcodeXpress 遷移的團隊報告以下觸發因素:
評估模式阻礙準確基準測試: 沒有有效的 OEM/運行時密鑰,BarcodeXpress 在解碼結果中蓋上 "UNLICENSED accusoft.com" 字樣,並在生成的 2D 條碼上應用相同印章。 預購精確度測試在真實文件上產生這樣的水印輸出,因此在購買之前,您無法驗證該庫是否正確讀取實際掃描型別。
雙鑰授權增加操作開銷: BarcodeXpress 將 SDK 授權(SetSolutionName 和 SetSolutionKey)與 OEM/運行時授權(SetOEMLicenseKey)分開。 CI/CD 管道、Docker 容器和容器協調器各自需要將兩個密鑰系統作為單獨的秘密進行管理。 缺失或無效的運行時密鑰導致水印輸出,而不是引發錯誤,從而建立了一種在自動化測試中可能通過非空結果檢查的失敗模式。
任何生產部署至少需要五個運行時授權: 即使是單伺服器部署也需要購買至少五個運行時授權。 在運行一個生產伺服器和一個預備伺服器的團隊,即使是實際使用,也必須至少支付十個運行時授權的費用。
40 PPM 標準版上限: 標準版將處理速度限制為每分鐘 40 頁。 在這個速度下,處理 100,000 份文件大約需要 41 小時。 要刪除上限需要升級到專業版,這會在開發者席位費用之外再增加費用。
無原生 PDF 支援: 必須使用單獨的庫將 PDF 文件渲染到影像,然後 BarcodeXpress 才能讀取它們。 此外部相依性增加了第二授權費用、轉換步驟以及保持渲染後的頁面影像所需的額外記憶體壓力。
執行緒安全需要實例隔離: BarcodeXpress 的 reader 物件有狀態,且不適合並發存取。 並行批量處理需要每個執行緒一個完全初始化的 BarcodeXpress 實例,在每個執行緒上下文中重複完整的雙層授權初始化。
基本問題
BarcodeXpress 在讀取任何條碼之前需要多步初始化、位圖載入以及 BarcodeType[] 配置:
using var bitmap = new Bitmap(imagePath);
var barcodeXpress = new BarcodeXpress(".");
barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
barcodeXpress.Licensing.SetOEMLicenseKey("2.0.OEMLicenseStringFromAccusoft...");
barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.DataMatrixBarcode,
BarcodeType.QRCodeBarcode
};
Result[] results = barcodeXpress.reader.Analyze(bitmap);
var value = results.FirstOrDefault()?.BarcodeValue;
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 用一個靜態調用替換了這整個塊:
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:功能比較
| 功能 | Accusoft BarcodeXpress | IronBarcode |
|---|---|---|
| 授權模式 | SDK 密鑰 + OEM/運行時密鑰(單獨購買) | 單一永久密鑰 |
| 最少運行時授權 | 5(即使是 1 伺服器) | 無運行時授權概念 |
| 評估模式 | 解碼值和生成的 2D 條碼被印上 "UNLICENSED accusoft.com" | 返回完整值; 僅在生成的輸出上水印 |
| 吞吐量限制 | 40 PPM(標準版) | 在任何層級都無限制 |
| 格式自動檢測 | 手動——必須將 BarcodeType[] 陣列指定給 BarcodeTypes |
自動跨所有支援的格式 |
| PDF 支援 | 需要單獨的庫來將頁面呈現為位圖 | 原生——BarcodeReader.Read("doc.pdf") |
| API 風格 | 基於實例; 位圖輸入; 屬性/方法配置 | 靜態工廠方法,流暢的 API |
| 執行緒安全 | 每個執行緒需要實例 | 無狀態靜態方法——執行緒安全 |
| Docker 授權配置 | 授權檔案裝載或授權伺服器 | 單一環境變數 |
| CI/CD 機密要求 | SDK 密鑰對 + OEM/運行時密鑰 | 一個機密 |
| .NET Framework / .NET Core | 單獨的包:Accusoft.BarcodeXpress.Net 和 Accusoft.BarcodeXpress.NetCore |
單一 IronBarcode 包(.NET Framework 4.6.2+, .NET Core 3.1+, .NET 5–8) |
| Linux/macOS | 是的(通過 .NetCore 包) | 是的——Windows x64/x86,Linux x64,macOS x64/ARM |
| 帶標誌的 QR 碼 | 需要手動 GDI+ 覆蓋 | 內建 AddBrandLogo("logo.png") |
| 價格入門點 | $1,960+ SDK + 最少 5 個運行時授權 | $749 永久(Lite,1 開發者) |
| 永久授權 | 不標準——聯絡銷售 | 是的,所有層級 |
快速入門:從Accusoft BarcodeXpress遷移到 IronBarcode
步驟 1:替換 NuGet 包
dotnet remove package Accusoft.BarcodeXpress.NetCore
dotnet add package IronBarcode
dotnet remove package Accusoft.BarcodeXpress.NetCore
dotnet add package IronBarcode
步驟 2:更新命名空間
// Remove
using Accusoft.BarcodeXpressSdk;
// Add
using IronBarCode;
// Remove
using Accusoft.BarcodeXpressSdk;
// Add
using IronBarCode;
Imports IronBarCode
步驟 3:初始化授權
在 Startup.cs 或您的相依注入配置中,僅在應用程式啟動時新增一次授權初始化:
// 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"
在生產中,從環境變數或您的機密管理器中讀取密鑰:
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"))
沒有 SetSolutionKey,沒有 SetOEMLicenseKey,沒有每伺服器運行時啟用。 這是完整的授權設置。
程式碼遷移範例
授權初始化
BarcodeXpress 方法:
using Accusoft.BarcodeXpressSdk;
public class BarcodeService
{
private readonly BarcodeXpress _barcodeXpress;
public BarcodeService()
{
// Constructor takes the path containing the Barcode Xpress runtime files.
_barcodeXpress = new BarcodeXpress(".");
// SDK license
_barcodeXpress.Licensing.SetSolutionName("AcmeCorp");
_barcodeXpress.Licensing.SetSolutionKey(1, 2, 3, 4);
// OEM/runtime license — separate purchase, minimum 5 licenses required.
// Without this call, decoded values and generated 2D barcodes are
// stamped with " UNLICENSED accusoft.com ".
_barcodeXpress.Licensing.SetOEMLicenseKey(
"2.0.OEMLicenseStringFromAccusoft...");
}
}
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
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
BarcodeXpress 建構函式僅存在於管理兩個授權密鑰系統和運行時路徑。IronBarcode在應用程式啟動時用一行代替它。BarcodeService 類別根本不需要建構函式。
條碼閱讀
BarcodeXpress 方法:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public string ReadFirstBarcode(string imagePath)
{
// Analyze takes a System.Drawing.Bitmap; the SDK does not read PDFs directly.
using var bitmap = new Bitmap(imagePath);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.DataMatrixBarcode,
BarcodeType.QRCodeBarcode
};
Result[] results = _barcodeXpress.reader.Analyze(bitmap);
return results.FirstOrDefault()?.BarcodeValue;
}
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
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
BarcodeTypes 陣列篩選器和 new Bitmap(...) 載入步驟都消失了。IronBarcode自動檢測所有支援的符號格式,並直接接受檔案路徑。 如果供應商從 Code 128 切換到 DataMatrix,IronBarcode 無需任何程式碼更改即可繼續運行。 結果屬性名稱也會改變:BarcodeValue 變成 BarcodeType 變成 Format。 整個方案的搜尋和替換即可處理這兩個替換。
從一個影像讀取多個條碼
BarcodeXpress 方法:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public IReadOnlyList<string> ReadAllBarcodes(string imagePath)
{
using var bitmap = new Bitmap(imagePath);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.QRCodeBarcode
};
Result[] results = _barcodeXpress.reader.Analyze(bitmap);
return results.Select(r => r.BarcodeValue).ToList();
}
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
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 告訴IronBarcode在第一次匹配後繼續掃描,這對於具有多個不同區域條碼的文件非常有用。 有關讀取選項的更多詳情,請參閱 IronBarcode 讀取文件。
批量處理
BarcodeXpress 是基於實例的,其 reader 物件有狀態,因此並行批量處理需要每個執行緒一個實例,並在每個執行緒中重複完整的雙層授權初始化。IronBarcode的靜態方法是無狀態的,所以 Parallel.ForEach 不需要實例管理。
BarcodeXpress 方法:
using System.Collections.Generic;
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
var results = new Dictionary<string, string>();
foreach (var path in imagePaths)
{
using var bitmap = new Bitmap(path);
_barcodeXpress.reader.BarcodeTypes = new[]
{
BarcodeType.Code128Barcode,
BarcodeType.QRCodeBarcode
};
Result[] barcodes = _barcodeXpress.reader.Analyze(bitmap);
if (barcodes.Length > 0)
results[path] = barcodes[0].BarcodeValue;
}
return results;
}
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
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
如果 BarcodeXpress 標準版的每分鐘 40 頁上限導致您新增速率限制處理程式碼 — 在每 40 組之間保持休眠、追蹤按分鐘計算或加入延遲 — 則應完全刪除該程式碼。IronBarcode沒有吞吐量上限。
新增 PDF 支援
BarcodeXpress 無法直接從 PDF 文件讀取條碼。 通常的解決方法是新增獨立的 PDF 渲染庫,將每個頁面渲染到記憶體中的影像,然後一次傳遞這些影像到條碼閱讀器。
BarcodeXpress 方法:
// Requires a separate PDF library (not shown — varies by team choice)
// Pattern: render each PDF page to a Bitmap, then pass it to Analyze.
foreach (Bitmap pageBitmap in pdfRenderer.RenderPages("document.pdf"))
{
using (pageBitmap)
{
_barcodeXpress.reader.BarcodeTypes = Enum.GetValues(typeof(BarcodeType));
Result[] barcodes = _barcodeXpress.reader.Analyze(pageBitmap);
// ... collect results
}
}
// 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
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
如果 itext7 或任何其他 PDF 庫僅僅為了支持 BarcodeXpress 閱讀工作流而新增,可以在遷移後予以刪除。 如需更多選項,包括頁面範圍選擇,請參閱 IronBarcode PDF 讀取指南。
條碼生成
BarcodeXpress 方法:
using System.Drawing;
using Accusoft.BarcodeXpressSdk;
public void GenerateBarcode(string data, string outputPath)
{
_barcodeXpress.writer.BarcodeType = BarcodeType.Code128Barcode;
_barcodeXpress.writer.BarcodeValue = data;
// CreateBitmap returns a System.Drawing.Bitmap; persist via Bitmap.Save.
using Bitmap bitmap = _barcodeXpress.writer.CreateBitmap();
bitmap.Save(outputPath);
}
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
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
流暢鏈取代了屬性分配、CreateBitmap 調用和 Bitmap.Save 步驟。要獲取條碼作為二進制資料以儲存在資料庫或 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()
QR 碼生成
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
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")
商標嵌入、錯誤修正級別和顏色自定義都內建在流暢的 API 中。 BarcodeXpress 需要在最初檔案寫入後手動 GDI+ 繪製以獲得這些功能中的任何一個。 更多的 QR 碼選項,請參閱 QR 碼生成指南。
Accusoft BarcodeXpress API 到IronBarcode映射參考
| Accusoft BarcodeXpress | IronBarcode |
|---|---|
new BarcodeXpress(".") |
靜態方法——無需實例 |
Licensing.SetSolutionName("...") |
IronBarCode.License.LicenseKey = "key" |
Licensing.SetSolutionKey(a, b, c, d) |
(removed — not needed) |
Licensing.SetOEMLicenseKey(string) |
(removed — no OEM/runtime key concept) |
new Bitmap(path) + reader.Analyze(bitmap) |
BarcodeReader.Read(path) |
reader.BarcodeTypes = new[] { BarcodeType.Code128Barcode, ... } |
(removed — auto-detection handles all formats) |
result.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 標準限制 | 在任何層級都無吞吐量限制 |
常見遷移問題及解決方案
問題 1:屬性名稱編譯錯誤
BarcodeXpress: 結果物件暴露 BarcodeValue 和 BarcodeType,而這在IronBarcode中不存在。
解決方案: 在建置之前執行整個方案的搜尋和替換:
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
將 result.BarcodeValue 替換為 result.Value,將 result.BarcodeType 替換為 result.Format 在所有找到的檔案中。
問題 2:孤立的授權配置呼叫
BarcodeXpress: SetSolutionKey 和 SetOEMLicenseKey 呼叫 — 外加任何自定義的斷言檢測解碼輸出中的 "UNLICENSED accusoft.com" 水印 — 存在於許多程式碼庫中作為防禦水印輸出失敗模式的方法。
解決方案: 定位並刪除所有這樣的呼叫位置 ——IronBarcode沒有等效的狀態。 授權密鑰要麼有效要麼無效,如果無效,則試用限制統一適用而不是降低單個解碼值:
grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "UNLICENSED accusoft" --include="*.cs" .
grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "UNLICENSED accusoft" --include="*.cs" .
所有這些呼叫位置都可以刪除。
問題 3:Docker 授權檔案裝載到環境變數
BarcodeXpress: Docker 部署通常使用 COPY 或卷裝載指令將 BarcodeXpress 授權配置檔案裝載到容器中的已知路徑。
解決方案: 移除配置檔案複製,並以環境變數替代:
# Remove this
COPY accusoft-license.lic /app/license/
# Add this
ENV IRONBARCODE_LICENSE=YOUR-LICENSE-KEY
在應用程式啟動時:
IronBarCode.License.LicenseKey =
Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");
IronBarCode.License.LicenseKey =
Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE");
Imports System
IronBarCode.License.LicenseKey = Environment.GetEnvironmentVariable("IRONBARCODE_LICENSE")
在 Kubernetes 中,授權密鑰在 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
問題 4:速率限制處理程式碼
BarcodeXpress: 處理在標準版 40-PPM 上限下的大批量文件的團隊通常會加入程式碼,以在多份文件群組間休眠,跟踪每分鐘計數,或者引入延遲以保持在限制內。
解決方案: 刪除所有速率限制程式碼。 用以下命令定位它:
grep -r "40\|PPM\|pagesPerMinute\|minuteStart" --include="*.cs" .
grep -r "40\|PPM\|pagesPerMinute\|minuteStart" --include="*.cs" .
IronBarcode 沒有吞吐量上限——以您基礎結構支援的任何速度進行處理。
問題 5:執行緒安全——移除實例池
BarcodeXpress: 支援並行處理的程式碼庫通常維護一個 BarcodeXpress 實例池或使用 ThreadLocal<BarcodeXpress> 模式來隔離每個執行緒的有狀態閱讀器。
解決方案: 完全刪除池化邏輯。IronBarcode的 BarcodeReader.Read 和 BarcodeWriter.CreateBarcode 是無狀態靜態方法。 來自任何數量執行緒的並行呼叫不會相互干擾。
Accusoft BarcodeXpress遷移檢查清單
遷移前任務
審核程式碼庫以識別在進行任何程式碼更改之前所有 BarcodeXpress 用途:
grep -r "BarcodeXpress" --include="*.cs" .
grep -r "Accusoft" --include="*.cs" .
grep -r "SetSolutionName" --include="*.cs" .
grep -r "SetSolutionKey" --include="*.cs" .
grep -r "SetOEMLicenseKey" --include="*.cs" .
grep -r "reader\.Analyze" --include="*.cs" .
grep -r "writer\.CreateBitmap" --include="*.cs" .
grep -r "\.BarcodeValue" --include="*.cs" .
grep -r "\.BarcodeType" --include="*.cs" .
grep -r "BarcodeType\." --include="*.cs" .
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" .
- 記下哪些條碼格式在
BarcodeTypes指派中被明確列出——這些在IronBarcode中都變為自動檢測 - 確認可以刪除的任何速率限制處理程式碼
- 確認僅為支持 BarcodeXpress 閱讀而新增的任何 PDF 渲染庫——這些也可以刪除
- 獲取您的IronBarcode授權密鑰並將其新增到您的機密管理器中
程式碼更新任務
- 從所有
Accusoft.BarcodeXpress.NetCore檔案中刪除.csproj - 將
IronBarcode新增到需要條碼功能的所有.csproj檔案中 - 在所有檔案中,用
using Accusoft.BarcodeXpressSdk;替換using IronBarCode; - 新增
IronBarCode.License.LicenseKey = ...到應用程式啟動 - 刪除所有
BarcodeXpress建構函式呼叫和實例欄位 - 刪除所有
SetSolutionKey和SetOEMLicenseKey呼叫 - 刪除所有掃描解碼輸出中的 "UNLICENSED accusoft.com" 水印的自定義斷言
- 將
new Bitmap(path)+reader.Analyze(bitmap)替換為BarcodeReader.Read(path) - 刪除所有
reader.BarcodeTypes = ...指派 - 將
result.BarcodeValue替換為result.Value - 將
result.BarcodeType替換為result.Format - 將
writer.CreateBitmap()+bitmap.Save(path)替換為BarcodeWriter.CreateBarcode(data, encoding).SaveAsPng(path) - 刪除速率限制調節程式碼
- 移除中介 PDF 渲染程式碼(如果存在)
- 刪除 BarcodeXpress 實例的實例池或
ThreadLocal模式 - 從 Dockerfile 和 docker-compose 檔案中移除授權檔案裝載
- 新增
IRONBARCODE_LICENSE環境變數到 Docker 和容器配置中 - 更新 Kubernetes 機密和pod 規範
- 更新 CI/CD 管線機密——移除
ACCUSOFT_SOLUTION_KEY和ACCUSOFT_RUNTIME_KEY; 新增IRONBARCODE_LICENSE
遷移後測試
- 構建解決方案——修復重命名屬性後的任何剩餘編譯錯誤
- 對所有條碼讀取運算進行單元測試
- 對所有條碼生成運算進行單元測試
- 如果適用的話,用 PDF 輸入進行測試
- 運行批量處理測試,以確認無吞吐量限制行為
- 部署到預備環境,並確認授權密鑰能從環境變數中正確解析
遷移到IronBarcode的主要優勢
消除雙鑰授權複雜性: 套裝 SetSolutionKey 和 SetOEMLicenseKey 完全消失。 一個密鑰涵蓋從開發到生產的每個環境,並且試用模式返回完整的解碼值(而不是蓋上 "UNLICENSED accusoft.com" 標記),以便在真實文件上進行預購基準測試成為可能。
無運行時授權最低購買量: BarcodeXpress 要求任何生產部署至少需要五個運行時授權。IronBarcode沒有運行時授權概念——單一永久密鑰涵蓋其層級內的任何數量的生產部署。
無上限的吞吐量: 標準版 40-PPM 上限和任何為保持範圍內而編寫的速率限制程式碼可以被刪除。IronBarcode的處理速度按照底層硬體和網路支援的速度運行,在任何價格層級上都沒有由軟體強加的上限。
原生 PDF 閱讀: BarcodeReader.Read("document.pdf") 直接處理 PDF 文件,返回含有頁碼、格式、值和置信度分數的每頁結果。 僅為支持 BarcodeXpress 而新增的任何 PDF 渲染庫可以被刪除,從而減少相依性和授權成本。
無狀態執行緒安全: BarcodeReader.Read 和 BarcodeWriter.CreateBarcode 是無狀態靜態方法。 實例池、ThreadLocal 模式和每個執行緒初始化區塊都可以被移除。 使用 Parallel.ForEach 進行並行處理不需要除了移除執行緒解決方案外的任何結構更改。
簡化的容器部署: Docker 和 Kubernetes 部署使用單一環境變數進行授權配置。 授權文件分發、授權伺服器基礎架構和配置文件裝載全部被消除。
常見問題
為什麼我應該從Accusoft BarcodeXpress遷移到IronBarcode?
常見的理由包括簡化授權(去除SDK +運行時鑰匙的複雜性)、消除吞吐量限制、獲得原生PDF支持、改善Docker/CI/CD部署,並減少生產程式碼中的API樣板。
我如何用IronBarcode替換Accusoft BarcodeXpress API呼叫?
用IronBarCode.License.LicenseKey = "key"替換實例建立和授權樣板。用BarcodeReader.Read(path)替換讀取呼叫,用BarcodeWriter.CreateBarcode(data, encoding)替換寫入呼叫。靜態方法不需要實例管理。
從Accusoft BarcodeXpress遷移到IronBarcode時需要更改多少程式碼?
大多數遷移會導致較少的程式碼行。授權樣板、實例構造函式和顯式格式配置被移除。核心讀/寫操作映射為較短的IronBarcode等價物,且結果物件更清晰。
遷移期間我需要同時安裝Accusoft BarcodeXpress和IronBarcode嗎?
不需要。大多數遷移是直接替換而不是並行操作。一次遷移一個服務類,替換NuGet引用,並更新實例化和API呼叫模式後再移動到下一個類。
IronBarcode的NuGet包名稱是什麼?
包名是'IronBarCode'(大寫B和C)。可以用'Install-Package IronBarCode'或'dotnet add package IronBarCode'安裝。程式碼中的using指令是'using IronBarCode;'。
IronBarcode如何簡化與Accusoft BarcodeXpress相比的Docker部署?
IronBarcode是沒有外部SDK文件或掛載許可配置的NuGet封裝。在Docker中,設置IRONBARCODE_LICENSE_KEY環境變數,包在啟動時處理許可驗證。
從Accusoft BarcodeXpress遷移後,IronBarcode會自動檢測所有的條碼格式嗎?
是的。IronBarcode自動檢測所有支持的格式的符號學。不需要顯式的BarcodeTypes枚舉。如果格式已經知道並且性能很重要,BarcodeReaderOptions允許限制搜索空間作為優化。
IronBarcode是否可以不使用單獨的庫讀取PDF中的條碼?
可以。BarcodeReader.Read("document.pdf")原生處理PDF文件。結果包括每個條碼發現的頁碼、格式、值和置信度。不需要外部PDF渲染步驟。
IronBarcode如何處理並行條碼處理?
IronBarcode的靜態方法是無狀態且執行緒安全的。直接使用Parallel.ForEach遍歷文件列表,不需要每個執行緒的實例管理。BarcodeReaderOptions.MaxParallelThreads控制內部執行緒預算。
從Accusoft BarcodeXpress遷移到IronBarcode後,結果屬性會有什麼變化?
常見的重命名:BarcodeValue變為Value,BarcodeType變為Format。IronBarcode結果還新增了Confidence和PageNumber。整個解決方案的搜索和替換可處理現有結果處理程式碼中的重新命名。
我如何在CI/CD管道中設置IronBarcode授權?
將IRONBARCODE_LICENSE_KEY作為管道機密儲存,在應用程式啟動程式碼中分配IronBarCode.License.LicenseKey。一個機密涵蓋所有環境,包括開發、測試、分期和生產。
IronBarcode是否支持生成帶有自定義樣式的QR碼?
支持。QRCodeWriter.CreateQrCode()支持通過ChangeBarCodeColor()自定義顏色,通過AddBrandLogo()嵌入logo,可配置錯誤校正級別,以及包括PNG、JPG、PDF和流在內的多種輸出格式。

