Jak odczytywać i skanować kody kreskowe w C# używając NET MAUI
Migrating fromBarcodeLibto IronBarcode
Niniejszy przewodnik zawiera kompletną ścieżkę migracji zBarcodeLibdo IronBarcode for .NET dla programistów .NET. Obejmuje on powody, dla których zespoły decydują się na tę zmianę, krok po kroku wymianę pakietów, przykłady migracji kodu dla każdego popularnego wzorca BarcodeLib, pełną dokumentację API oraz uporządkowaną listę kontrolną do zarządzania migracją w całym kodzie źródłowym.
Dlaczego warto przejść z BarcodeLib
Zespoły migrujące zBarcodeLibdo IronBarcode zgłaszają następujące wyzwałącze:
Brak API do odczytu:BarcodeLibnigdy nie posiadał funkcji odczytu ani dekodowania. Gdy projekt generujący obrazy kodów kreskowych otrzymuje nowe wymaganie dotyczące skanowania kodów kreskowych — z przesłanych obrazów, skanerów magazynowych lub dokumentów dostawców —BarcodeLibnie jest w stanie go spełnić. Jedyną opcją jest dodanie drugiej biblioteki, takiej jak ZXing.Net, co wprowadza drugi graf zależności i drugą powierzchnię API, które należy utrzymywać równolegle z BarcodeLib.
Konflikt wersji SkiaSharp:BarcodeLib3.x wprowadził SkiaSharp jako backend graficzny w celu zastąpienia System.Drawing.Common. Biblioteka jest powiązana z konkretnym zakresem wersji SkiaSharp. W projektach MAUI, Blazor oraz w każdym projekcie, w którym inna zależność również pobiera SkiaSharp, wersja, do której doszło, często wykracza poza oczekiwany zakres BarcodeLib. Powoduje to wyświetlenie ostrzeżeń NU1608 podczas przywracania, a w najgorszym przypadku — błędy wiązania zestawów w czasie wykonywania na urządzeniu.
Brak obsługi plików PDF: Aplikacje generujące dokumenty PDF z osadzonymi BARCODE-ami — faktury, zlecenia pracy, listy przewozowe — czasami muszą odczytać te BARCODE-y podczas dalszego przetwarzania.BarcodeLibgeneruje obrazy kodów kreskowych, ale nie obsługuje PDF-ów na żadnym końcu. Wyodrębnianie kodów kreskowych z pliku PDF za pomocąBarcodeLibwymaga renderowania stron PDF do obrazów za pomocą oddzielnej biblioteki PDF, a następnie przekazania tych obrazów do oddzielnej biblioteki odczytu.
Kodowanie strumieniowe dla wyjścia z tablicą bajtów:BarcodeLib3.x zwraca SKImage, co wymaga etapu kodowania SkiaSharp do MemoryStream, aby uzyskać wyjście byte[], które wymaga narzędzi HTTP w odpowiedziach, kolumn BLOB w bazach danych i większości odbiorców w dół strumienia.IronBarcode zapewnia .ToPngBinaryData() bezpośrednio w łańcuchu generacji.
Podstawowy problem
ArchitekturaBarcodeLiboparta wyłącznie na generowaniu oznacza, że dodanie jakiejkolwiek funkcji skanowania wymusza wprowadzenie drugiej biblioteki do stosu:
// BarcodeLib: generation only — reading requires a completely separate library
using BarcodeStandard;
using SkiaSharp;
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100);
using var stream = File.OpenWrite("barcode.png");
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
// To read it back, a separate scanning library such as ZXing.Net is required —
// separate API, separate dependency graph to maintain alongside BarcodeLib.
// BarcodeLib: generation only — reading requires a completely separate library
using BarcodeStandard;
using SkiaSharp;
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100);
using var stream = File.OpenWrite("barcode.png");
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
// To read it back, a separate scanning library such as ZXing.Net is required —
// separate API, separate dependency graph to maintain alongside BarcodeLib.
Imports BarcodeStandard
Imports SkiaSharp
Dim b = New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, "PRODUCT-12345", 300, 100)
Using stream = File.OpenWrite("barcode.png")
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
IronBarcode obsługuje oba w tym samym pakiecie z tym samym using oświadczeniem:
// IronBarcode: generation and reading — no second library needed
using IronBarCode;
// Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("barcode.png");
// Read back — same package, same namespace
var result = BarcodeReader.Read("barcode.png").First().Value;
Console.WriteLine(result); // "PRODUCT-12345"
// IronBarcode: generation and reading — no second library needed
using IronBarCode;
// Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.SaveAsPng("barcode.png");
// Read back — same package, same namespace
var result = BarcodeReader.Read("barcode.png").First().Value;
Console.WriteLine(result); // "PRODUCT-12345"
Imports IronBarCode
' Generate
BarcodeWriter.CreateBarcode("PRODUCT-12345", BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.SaveAsPng("barcode.png")
' Read back — same package, same namespace
Dim result = BarcodeReader.Read("barcode.png").First().Value
Console.WriteLine(result) ' "PRODUCT-12345"
IronBarcode a BarcodeLib: porównanie funkcji
| Funkcja | BarcodeLib | IronBarcode |
|---|---|---|
| Generowanie BarCode'ów | Tak | Tak |
| Odczytywanie/skanowanie BarCode | Nie | Tak (BarcodeReader.Read()) |
| Generowanie kodów QR | Nie (tylko 1D) | Tak (zaawansowane, z osadzeniem logo) |
| Odczytywanie BarCodes z plików PDF | Nie | Tak (język ojczysty, bez dodatkowej biblioteki) |
| Wynik generowania BarCodes w formacie PDF | Nie | Tak |
| Zależność SkiaSharp | Tak (ryzyko konfliktu wersji) | Nie |
| Kompatybilność z projektem MAUI | Ryzyko konfliktu (NU1608) | Bez konfliktu |
| Płynny, łańcuchowy interfejs API | Nie | Tak |
byte[] wyjście bezpośrednio |
Ręcznie (przez MemoryStream) |
.ToPngBinaryData() |
| Wykrywanie wielu kodów BarCode | Nie | Tak (ExpectMultipleBarcodes) |
| Dostosowanie szybkości czytania | Nie dotyczy | Tak (ReadingSpeed enum) |
| Obsługa systemów Linux / macOS | Częściowe (zależne od SkiaSharp) | Pełna |
| Obsługa Docker / kontenerów | Wymagana konfiguracja | Tak |
| Aktywna konserwacja | Tak (społeczność) | Tak (komercyjne) |
| Wsparcie komercyjne / SLA | Nie | Tak |
| Licencja | Apache 2.0 (bezpłatna) | $999–$5,999 wieczysta |
Szybki start: Migracja zBarcodeLibdo IronBarcode
Migrację można rozpocząć natychmiast, wykonując te podstawowe kroki.
Krok 1: Zastąp pakiet NuGet
Usuń najpierw pakiet BarcodeLib:
dotnet remove package BarcodeLib
dotnet remove package BarcodeLib
Jeśli nie jesteś pewien, jak jest to referowane, sprawdź plik .csproj:
grep -n "BarcodeLib" YourProject.csproj
grep -n "BarcodeLib" YourProject.csproj
Usuń wszystkie wpisy <PackageReference> związane z BarcodeLib. Jeśli dodałeś jawne <PackageReference Include="SkiaSharp"> zastąpienia, aby obejść ostrzeżenia NU1608 z BarcodeLib, usuń je również — po zainstalowaniu IronBarcode, oceń, czy SkiaSharp jest nadal potrzebny z innych powodów. Następnie zainstaluj IronBarcode:
dotnet add package IronBarcode
dotnet add package IronBarcode
Krok 2: Aktualizacja przestrzeni nazw
Zastąp dyrektywy usingBarcodeLibw każdym pliku, który je referował:
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
// Before
using BarcodeStandard;
using SkiaSharp;
// After
using IronBarCode;
Imports IronBarCode
Imports SkiaSharp
Krok 3: Inicjalizacja licencji
Dodaj inicjalizację licencji podczas uruchamiania aplikacji:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
Dla aplikacji ASP.NET Core umieść to w Program.cs przed builder.Build(). Dla aplikacji konsolowych umieść to na początku Main(). W przypadku bibliotek klas wywoływanych z innych aplikacji należy je zainicjować w momencie uruchomienia aplikacji hosta.
Przykłady migracji kodu
Podstawowe generowanie kodu 128
Najczęstszy wzorzec BarcodeLib: stwórz instancję, ustaw właściwości, wywołaj Encode().
Podejście BarcodeLib:
using BarcodeStandard;
using SkiaSharp;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
var b = new Barcode();
b.IncludeLabel = true;
SKImage img = b.Encode(Type.Code128, trackingNumber, 400, 120);
using var stream = File.OpenWrite(outputPath);
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
}
using BarcodeStandard;
using SkiaSharp;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
var b = new Barcode();
b.IncludeLabel = true;
SKImage img = b.Encode(Type.Code128, trackingNumber, 400, 120);
using var stream = File.OpenWrite(outputPath);
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream);
}
Imports BarcodeStandard
Imports SkiaSharp
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
Dim b As New Barcode()
b.IncludeLabel = True
Dim img As SKImage = b.Encode(Type.Code128, trackingNumber, 400, 120)
Using stream = File.OpenWrite(outputPath)
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(stream)
End Using
End Sub
Podejście IronBarcode:
// NuGet: dotnet add package IronBarcode
using IronBarCode;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.AddAnnotationTextBelowBarcode(trackingNumber)
.SaveAsPng(outputPath);
}
// NuGet: dotnet add package IronBarcode
using IronBarCode;
public void GenerateShippingLabel(string trackingNumber, string outputPath)
{
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.AddAnnotationTextBelowBarcode(trackingNumber)
.SaveAsPng(outputPath);
}
Imports IronBarCode
Public Sub GenerateShippingLabel(trackingNumber As String, outputPath As String)
BarcodeWriter.CreateBarcode(trackingNumber, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.AddAnnotationTextBelowBarcode(trackingNumber) _
.SaveAsPng(outputPath)
End Sub
Blok ustawiający właściwości zwija się w płynny łańcuch. .AddAnnotationTextBelowBarcode() zastępuje b.IncludeLabel = true — akceptuje ciąg etykiety jawnie, więc kontrolujesz, jaki tekst pojawi się poniżej pasków. .ResizeTo() zastępuje argumenty szerokości/wysokości. Aby uzyskać informacje na temat zaawansowanych opcji generowania, zapoznaj się z dokumentacją dotyczącą generowania kodów kreskowych IronBarcode.
Zwracanie byte[] — typowy wzorzec API sieci Web
BarcodeLib 3.x zwraca SKImage. Uzyskanie bajtów z niego wymaga kodowania przez SkiaSharp do MemoryStream.IronBarcode zapewnia .ToPngBinaryData() bezpośrednio.
Podejście BarcodeLib:
using BarcodeStandard;
using SkiaSharp;
using System.IO;
public byte[] GetBarcodeBytes(string data)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
}
using BarcodeStandard;
using SkiaSharp;
using System.IO;
public byte[] GetBarcodeBytes(string data)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
}
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
Public Function GetBarcodeBytes(data As String) As Byte()
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
End Function
Podejście IronBarcode:
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
using IronBarCode;
public byte[] GetBarcodeBytes(string data)
{
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
}
Imports IronBarCode
Public Function GetBarcodeBytes(data As String) As Byte()
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
End Function
MemoryStream pośredni etap został usunięty. .ToPngBinaryData() zwraca byte[] bezpośrednio, co jest potrzebne w ciałach odpowiedzi HTTP, kolumnach BLOB w bazach danych i zapisach plików.
Akcja kontrolera Web API
Podejście BarcodeLib:
using BarcodeStandard;
using SkiaSharp;
using Microsoft.AspNetCore.Mvc;
using System.IO;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, sku, 400, 120);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return File(ms.ToArray(), "image/png");
}
}
using BarcodeStandard;
using SkiaSharp;
using Microsoft.AspNetCore.Mvc;
using System.IO;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
var b = new Barcode();
SKImage img = b.Encode(Type.Code128, sku, 400, 120);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return File(ms.ToArray(), "image/png");
}
}
Imports BarcodeStandard
Imports SkiaSharp
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim b As New Barcode()
Dim img As SKImage = b.Encode(Type.Code128, sku, 400, 120)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return File(ms.ToArray(), "image/png")
End Using
End Function
End Class
Podejście IronBarcode:
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
byte[] pngBytes = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.ToPngBinaryData();
return File(pngBytes, "image/png");
}
}
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/labels")]
public class LabelsController : ControllerBase
{
[HttpGet("{sku}")]
public IActionResult GetLabel(string sku)
{
byte[] pngBytes = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.ToPngBinaryData();
return File(pngBytes, "image/png");
}
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/labels")>
Public Class LabelsController
Inherits ControllerBase
<HttpGet("{sku}")>
Public Function GetLabel(sku As String) As IActionResult
Dim pngBytes As Byte() = BarcodeWriter.CreateBarcode(sku, BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.ToPngBinaryData()
Return File(pngBytes, "image/png")
End Function
End Class
Działanie kontrolera zmniejsza się po usunięciu bloku MemoryStream i etapu kodowania SkiaSharp. Tablica bajtów płynie bezpośrednio od .ToPngBinaryData() do File().
Generowanie kodów QR
BarcodeLib 3.x nie generuje kodów QR — enum BarcodeStandard.Type nie zawiera wpisów 2D. Projekty, które potrzebowały QR obok BarcodeLib, zazwyczaj dodawały drugą bibliotekę, taką jak QRCoder.IronBarcode używa dedykowanej klasy QRCodeWriter z dodatkowymi opcjami do osadzenia logo i stylizacji.
Podejście BarcodeLib:
//BarcodeLibhas no QR Code (or any 2D) support.
// Generating a QR code from aBarcodeLibproject required adding a
// second library such as QRCoder:
//
// using QRCoder;
// var qrGen = new QRCodeGenerator();
// var data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q);
// // ... separate API, separate dependency to maintain.
//BarcodeLibhas no QR Code (or any 2D) support.
// Generating a QR code from aBarcodeLibproject required adding a
// second library such as QRCoder:
//
// using QRCoder;
// var qrGen = new QRCodeGenerator();
// var data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q);
// // ... separate API, separate dependency to maintain.
' BarcodeLib has no QR Code (or any 2D) support.
' Generating a QR code from a BarcodeLib project required adding a
' second library such as QRCoder:
'
' Imports QRCoder
' Dim qrGen As New QRCodeGenerator()
' Dim data = qrGen.CreateQrCode("https://example.com/product/42", QRCodeGenerator.ECCLevel.Q)
' ' ... separate API, separate dependency to maintain.
Podejście IronBarcode:
using IronBarCode;
// Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.SaveAsPng("qr.png");
// QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded.png");
using IronBarCode;
// Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.SaveAsPng("qr.png");
// QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300)
.AddBrandLogo("logo.png")
.SaveAsPng("qr-branded.png");
Imports IronBarCode
' Basic QR code
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300) _
.SaveAsPng("qr.png")
' QR code with embedded brand logo (not possible with BarcodeLib)
QRCodeWriter.CreateQrCode("https://example.com/product/42", 300) _
.AddBrandLogo("logo.png") _
.SaveAsPng("qr-branded.png")
QRCodeWriter.CreateQrCode() przyjmuje ciąg danych i rozmiar piksela jako parametry. Osadzanie logo, dostosowanie kolorów i poziom korekcji błędów są dostępne poprzez łańcuchowe metody. Dla opcji stylizacji kodu QR, zobacz dokumentację kodu QR IronBarcode.
EAN-13 i UPC-A
Są one powszechnie stosowane w systemach inwentaryzacji handlowej. Nazwy enum zmieniają się, ale wartości są bezpośrednimi odpowiednikami.
Podejście BarcodeLib:
using BarcodeStandard;
using SkiaSharp;
// EAN-13 product barcode
var b = new Barcode();
SKImage ean = b.Encode(Type.Ean13, "5901234123457", 250, 100);
using (var s = File.OpenWrite("product-ean.png"))
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
// UPC-A for US retail
SKImage upc = b.Encode(Type.UpcA, "012345678905", 250, 100);
using (var s = File.OpenWrite("product-upc.png"))
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
using BarcodeStandard;
using SkiaSharp;
// EAN-13 product barcode
var b = new Barcode();
SKImage ean = b.Encode(Type.Ean13, "5901234123457", 250, 100);
using (var s = File.OpenWrite("product-ean.png"))
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
// UPC-A for US retail
SKImage upc = b.Encode(Type.UpcA, "012345678905", 250, 100);
using (var s = File.OpenWrite("product-upc.png"))
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s);
Imports BarcodeStandard
Imports SkiaSharp
Imports System.IO
' EAN-13 product barcode
Dim b As New Barcode()
Dim ean As SKImage = b.Encode(Type.Ean13, "5901234123457", 250, 100)
Using s = File.OpenWrite("product-ean.png")
ean.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
' UPC-A for US retail
Dim upc As SKImage = b.Encode(Type.UpcA, "012345678905", 250, 100)
Using s = File.OpenWrite("product-upc.png")
upc.Encode(SKEncodedImageFormat.Png, 100).SaveTo(s)
End Using
Podejście IronBarcode:
using IronBarCode;
// EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13)
.ResizeTo(250, 100)
.SaveAsPng("product-ean.png");
// UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA)
.ResizeTo(250, 100)
.SaveAsPng("product-upc.png");
using IronBarCode;
// EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13)
.ResizeTo(250, 100)
.SaveAsPng("product-ean.png");
// UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA)
.ResizeTo(250, 100)
.SaveAsPng("product-upc.png");
Imports IronBarCode
' EAN-13 product barcode
BarcodeWriter.CreateBarcode("5901234123457", BarcodeEncoding.EAN13) _
.ResizeTo(250, 100) _
.SaveAsPng("product-ean.png")
' UPC-A for US retail
BarcodeWriter.CreateBarcode("012345678905", BarcodeEncoding.UPCA) _
.ResizeTo(250, 100) _
.SaveAsPng("product-upc.png")
Dodanie funkcji odczytu BarCode (zupełnie nowa funkcja)
BarcodeLib nie ma API do odczytu. Jeśli migracja jest motywowana nowym wymaganiem skanowania kodów kreskowych — z przesyłanych obrazów, skanerów magazynowych lub skanowanych dokumentów PDF — dodaj to bez drugiej biblioteki:
Podejście BarcodeLib:
//BarcodeLib— no reading API exists
// Adding reading requires a separate library such as ZXing.Net:
// dotnet add package ZXing.Net
// using ZXing;
// var reader = new BarcodeReader();
// // ... separate API, separate dependency graph to manage
//BarcodeLib— no reading API exists
// Adding reading requires a separate library such as ZXing.Net:
// dotnet add package ZXing.Net
// using ZXing;
// var reader = new BarcodeReader();
// // ... separate API, separate dependency graph to manage
'BarcodeLib— no reading API exists
' Adding reading requires a separate library such as ZXing.Net:
' dotnet add package ZXing.Net
' Imports ZXing
' Dim reader As New BarcodeReader()
' ' ... separate API, separate dependency graph to manage
Podejście IronBarcode:
using IronBarCode;
// Read a barcode from an image file
var results = BarcodeReader.Read("incoming-label.png");
foreach (var result in results)
{
Console.WriteLine($"Value: {result.Value}");
Console.WriteLine($"Format: {result.Format}");
}
// Read all barcodes from a multi-page PDF — no PDF library required
var pdfResults = BarcodeReader.Read("supplier-invoice.pdf");
foreach (var result in pdfResults)
{
Console.WriteLine($"Page {result.PageNumber}: {result.Value}");
}
// Configure for high-volume scanning with multiple barcodes per image
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var warehouseResults = BarcodeReader.Read("dock-scan.png", options);
using IronBarCode;
// Read a barcode from an image file
var results = BarcodeReader.Read("incoming-label.png");
foreach (var result in results)
{
Console.WriteLine($"Value: {result.Value}");
Console.WriteLine($"Format: {result.Format}");
}
// Read all barcodes from a multi-page PDF — no PDF library required
var pdfResults = BarcodeReader.Read("supplier-invoice.pdf");
foreach (var result in pdfResults)
{
Console.WriteLine($"Page {result.PageNumber}: {result.Value}");
}
// Configure for high-volume scanning with multiple barcodes per image
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var warehouseResults = BarcodeReader.Read("dock-scan.png", options);
Imports IronBarCode
' Read a barcode from an image file
Dim results = BarcodeReader.Read("incoming-label.png")
For Each result In results
Console.WriteLine($"Value: {result.Value}")
Console.WriteLine($"Format: {result.Format}")
Next
' Read all barcodes from a multi-page PDF — no PDF library required
Dim pdfResults = BarcodeReader.Read("supplier-invoice.pdf")
For Each result In pdfResults
Console.WriteLine($"Page {result.PageNumber}: {result.Value}")
Next
' Configure for high-volume scanning with multiple barcodes per image
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim warehouseResults = BarcodeReader.Read("dock-scan.png", options)
BarcodeReader.Read() akceptuje pliki graficzne, pliki PDF, strumienie i obiekty System.Drawing.Bitmap. Enum ReadingSpeed pozwala zamienić dokładność na wydajność podczas skanowania większej ilości danych. Dla opcji konfiguracji czytania zobacz dokumentację czytania IronBarcode.
Rozwiązywanie konfliktu SkiaSharp
Jeśli migracja jest prowadzona przez ostrzeżenia NU1608, sprawdź, czy konflikt jest rozwiązany po zmianie pakietów. Po uruchomieniu dotnet remove package BarcodeLib i dotnet add package IronBarcode, zbuduj ponownie i sprawdź wyjście:
dotnet build 2>&1 | grep -i "NU1608<|SkiaSharp"
dotnet build 2>&1 | grep -i "NU1608<|SkiaSharp"
Jeśli wynik się nie pojawia, konflikt jest rozwiązany. Jeśli pozostają ostrzeżenia SkiaSharp, pochodzą one z innego pakietu w grafie zależności —IronBarcode nie jest źródłem.
Podejście BarcodeLib:
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BarcodeLib" Version="3.1.5" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
</ItemGroup>
Podejście IronBarcode:
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IronBarcode" Version="*" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="3.116.1" />
</ItemGroup>
Odniesienie do mapowania APIBarcodeLibna IronBarcode
| BarcodeLib | IronBarcode |
|---|---|
new Barcode() |
Statyczne API — nie jest wymagany egzemplarz |
b.Encode(Type.Code128, "data", w, h) |
BarcodeWriter.CreateBarcode("data", BarcodeEncoding.Code128) |
b.IncludeLabel = true |
.AddAnnotationTextBelowBarcode("text") |
Szerokość/wysokość przekazywana do Encode() |
.ResizeTo(width, height) |
Zwraca SKImage |
.SaveAsPng(path) / .ToPngBinaryData() |
Type.Code128 |
BarcodeEncoding.Code128 |
Type.Code39 |
BarcodeEncoding.Code39 |
Type.Ean13 |
BarcodeEncoding.EAN13 |
Type.UpcA |
BarcodeEncoding.UPCA |
| Brak wsparcia dla QR (tylko 1D) | BarcodeEncoding.QRCode (także QRCodeWriter) |
Type.Itf14 |
BarcodeEncoding.ITF14 |
Type.Codabar |
BarcodeEncoding.Codabar |
| Brak API do odczytu | BarcodeReader.Read(path) |
| Konflikt wersji SkiaSharp w MAUI | Brak konfliktowych zależności |
img.Encode(...).SaveTo(stream) |
.SaveAsPng(path) |
MemoryStream + kodowanie SkiaSharp |
.ToPngBinaryData() |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Zmiana przestrzeni nazw Enum typu
BarcodeLib 3.x: Używa BarcodeStandard.Type.Code128 (PascalCase, w przestrzeni nazw BarcodeStandard). Starszy kod 2.x może używać BarcodeLib.TYPE.CODE128 (stałe pisane wielkimi literami, przestrzeń nazw BarcodeLib) — obie formy pojawiają się w rzeczywistych bazach kodów w trakcie migracji.
Rozwiązanie: Zastąp BarcodeEncoding.Code128. Grep przez pliki .cs identyfikuje wszystkie wystąpienia:
grep -rn "Type\.\|TYPE\." --include="*.cs" .
grep -rn "Type\.\|TYPE\." --include="*.cs" .
Typowe zamienniki: Type.Code128 / TYPE.CODE128 → BarcodeEncoding.Code128, Type.Ean13 / TYPE.EAN13 → BarcodeEncoding.EAN13, Type.UpcA / TYPE.UPCA → BarcodeEncoding.UPCA, Type.Itf14 / TYPE.ITF14 → BarcodeEncoding.ITF14, Type.Codabar / TYPE.CO/DABAR → BarcodeEncoding.Codabar.BarcodeLibnie ma wpisu QR; każdy TYPE.QR_Code to martwy kod z wersji 2.x lub forka — zastąp BarcodeEncoding.QRCode (lub użyj QRCodeWriter dla stylizowanego wyjścia).
Problem 2: Zwracany typ SKImage / Image
BarcodeLib: b.Encode() zwraca SKImage w wersji 3.x i System.Drawing.Image w wersji 2.x. Każdy z typów nie będzie skompilowany z IronBarcode.
Rozwiązanie: Usuń pośrednią zmienną obrazu i zastąp logikę zapisu odpowiednią metodą końcową na łańcuchu fluent:
// Before (BarcodeLib 3.x)
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
// After
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
// Before (BarcodeLib 3.x)
SKImage img = b.Encode(Type.Code128, data, 300, 100);
using var ms = new MemoryStream();
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
return ms.ToArray();
// After
return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(300, 100)
.ToPngBinaryData();
Imports System.IO
' Before (BarcodeLib 3.x)
Dim img As SKImage = b.Encode(Type.Code128, data, 300, 100)
Using ms As New MemoryStream()
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms)
Return ms.ToArray()
End Using
' After
Return BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(300, 100) _
.ToPngBinaryData()
Przeszukaj wzory SKImage img = b.Encode i Image img = b.Encode, aby znaleźć wszystkie dotknięte lokalizacje.
Problem 3: Parametry szerokości i wysokości
BarcodeLib: Szerokość i wysokość są argumentami pozycyjnymi na Encode(Type, string, int, int) w wersji 3.x, a osobne przypisania właściwości b.Width / b.Height w starszym kodzie 2.x. Każda forma wymaga portowania.
Rozwiązanie: Szerokość/wysokość stają się jednym wywołaniem .ResizeTo(width, height) połączonym po CreateBarcode(). Znajdź miejsca wywołań:
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
# Find Encode() calls and any Width/Height property assignments
grep -n "\.Encode(\|\.Width = \|\.Height = " --include="*.cs" -r .
Następnie zastąp argumenty rozmiaru lub parę właściwości jednym wywołaniem łańcucha .ResizeTo(width, height).
Problem 4: Przełącznik Boolean IncludeLabel
BarcodeLib: b.IncludeLabel = true to boolean, który automatycznie renderuje zakodowany ciąg danych jako widoczny tekst poniżej pasków.
Rozwiązanie: Użyj .AddAnnotationTextBelowBarcode("text"), które przyjmuje ciąg etykiety jawnie. W większości przypadków podaj ten sam ciąg danych, który został zakodowany w kodzie kreskowym. Jeśli oryginalny kod używał IncludeLabel = true i polegał na BarcodeLib, aby automatycznie renderować dane jako etykietę, przekaż ten sam ciąg danych jawnie:
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.AddAnnotationTextBelowBarcode(data) // pass the same string
.SaveAsPng(outputPath);
Dim barcodeWriter = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
barcodeWriter.AddAnnotationTextBelowBarcode(data) ' pass the same string
barcodeWriter.SaveAsPng(outputPath)
Problem 5: Pozostawione odwołania SkiaSharp po usunięciu BarcodeLib
BarcodeLib: Projekty często gromadziły jawne wpisy <PackageReference Include="SkiaSharp">, aby specjalnie przezwyciężyć ograniczenia wersji BarcodeLib. Te stają się osierocone po usunięciu BarcodeLib.
Rozwiązanie: Po przejściu na IronBarcode, sprawdź, czy SkiaSharp wciąż jest potrzebny przez inny pakiet przed usunięciem jawnego odwołania:
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
# Check if SkiaSharp is still referenced by anything other than the explicit override
dotnet list package --include-transitive 2>&1 | grep -i skia
Jeśli SkiaSharp występuje tylko z powodu teraz usuniętego jawnego <PackageReference>, usuń ten wpis. Jeśli jest wciąż wciągany przez MAUI lub inną zależność, zostaw go —IronBarcode nie będzie z nim w konflikcie.
Lista kontrolna migracji BarcodeLib
Zadania przed migracją
Uruchom te wyszukiwania przed rozpoczęciem, aby zrozumieć zakres potrzebnych zmian:
# Find allBarcodeLibusing directives (both 3.x BarcodeStandard and older BarcodeLib)
grep -rn "using BarcodeStandard\|using BarcodeLib" --include="*.cs" .
# Find Barcode object instantiation
grep -rn "new Barcode()" --include="*.cs" .
# Find Encode calls
grep -rn "\.Encode(" --include="*.cs" .
# Find Type enum usage (3.x PascalCase and 2.x uppercase)
grep -rn "Type\.Code128\|Type\.Ean13\|Type\.UpcA\|TYPE\.CODE128\|TYPE\.EAN13\|TYPE\.UPCA" --include="*.cs" .
# Find IncludeLabel usage
grep -rn "IncludeLabel" --include="*.cs" .
# Find the package references in project files
grep -rn "BarcodeLib" --include="*.csproj" .
# Find NU1608 evidence in lock files
grep -rn "NU1608" .
# Find allBarcodeLibusing directives (both 3.x BarcodeStandard and older BarcodeLib)
grep -rn "using BarcodeStandard\|using BarcodeLib" --include="*.cs" .
# Find Barcode object instantiation
grep -rn "new Barcode()" --include="*.cs" .
# Find Encode calls
grep -rn "\.Encode(" --include="*.cs" .
# Find Type enum usage (3.x PascalCase and 2.x uppercase)
grep -rn "Type\.Code128\|Type\.Ean13\|Type\.UpcA\|TYPE\.CODE128\|TYPE\.EAN13\|TYPE\.UPCA" --include="*.cs" .
# Find IncludeLabel usage
grep -rn "IncludeLabel" --include="*.cs" .
# Find the package references in project files
grep -rn "BarcodeLib" --include="*.csproj" .
# Find NU1608 evidence in lock files
grep -rn "NU1608" .
Udokumentuj wszystkie pliki dotknięte przez każde wyszukiwanie. Zauważ, które projekty bezpośrednio referują BarcodeLib, a które dziedziczą go tranzytywnie. Zidentyfikuj wszelkie jawne zastąpienia wersji SkiaSharp dodane tylko w celu rozwiązania konfliktów BarcodeLib.
Zadania związane z aktualizacją kodu
- Uruchom
dotnet remove package BarcodeLibdla każdego projektu - Usuń wszelkie jawne zastąpienia wersji SkiaSharp dodane tylko do naprawy konfliktów BarcodeLib
- Uruchom
dotnet add package IronBarcodedla każdego projektu - Dodaj
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";do startu aplikacji w każdym projekcie - Zastąp
using BarcodeStandard;(lubusing BarcodeLib;w starszym kodzie) iusing SkiaSharp;przezusing IronBarCode;we wszystkich plikach.cs - Usuń importy
using System.Drawing.Imaging;pozostałe po użyciuImageFormat.Pngw wersji 2.x - Zastąp wywołania
new Barcode()+Encode()wywołaniami łańcucha fluentBarcodeWriter.CreateBarcode() - Zastąp
Type.Code128/TYPE.CODE128→BarcodeEncoding.Code128i wszystkie inne wartości enum - Zastąp argumenty szerokości/wysokości (lub 2.x
b.Width = N; b.Height = M;) with.ResizeTo(N, M)wywołania łańcucha - Zastąp
b.IncludeLabel = true;przez.AddAnnotationTextBelowBarcode(data) - Zastąp
img.Encode(SKEncodedImageFormat.Png, 100).SaveTo(...)przez.SaveAsPng(path)lub.ToPngBinaryData() - Usuń pośrednie zmienne
SKImage/Imagei blokiMemoryStream, gdzie.ToPngBinaryData()je zastępuje - Dodaj kod odczytu kodu kreskowego tam, gdzie potrzebny (
BarcodeReader.Read())
Testy po migracji
- Zbuduj projekt i potwierdź, że nie zostały żadne ostrzeżenia NU1608 w wyjściu odtwarzanym
- Uruchom
dotnet build 2>&1| grep -i "NU1608<|SkiaSharp", aby zweryfikować, że konflikt SkiaSharp jest w pełni rozwiązany - Porównaj wizualne wyniki generowanych kodów kreskowych ze znanymi dobrymi próbkami z BarcodeLib
- Zweryfikuj, że kody QR dekodują się poprawnie przy użyciu skanera mobilnego lub metody
BarcodeReader.Read() - Przetestuj kody EAN-13 i UPC-A na sprzęcie skanera detalicznego, jeśli jest to możliwe
- Zweryfikuj, że obrazy wyświetlają się poprawnie we wszystkich celach wyjściowych: systemie plików, odpowiedzi HTTP, magazynowaniu w bazie danych
- Przetestuj scenariusze odczytu kodów kreskowych w PDF, używając
BarcodeReader.Read("file.pdf")na rzeczywistych dokumentach - Potwierdź, że kompilacje międzyplatformowe kończą się sukcesem, jeśli projekt jest stosowany na Linuksie lub macOS
- Zweryfikuj, że budowy MAUI kończą się bez błędów związanych z powiązaniami SkiaSharp na docelowych Androidzie i iOS
Kluczowe korzyści wynikające z migracji do IronBarcode
Czytanie kodów kreskowych bez drugiej biblioteki: Najbardziej natychmiastową korzyścią dla zespołów, które potrzebowały zdolności czytania, jest eliminacja zależności od drugiej biblioteki. BarcodeReader.Read() jest w tym samym pakiecie, używa tego samego using IronBarCode; statement i nie wymaga dodatkowych instalacji NuGet. ZXing.Net i jego własna zależność są już poza projektem.
Brak konfliktu wersji SkiaSharp:IronBarcode nie dzieli grafu zależności SkiaSharp z kodem aplikacji. Projekty MAUI, projekty Blazor oraz każdy projekt, w którym wiele pakietów zbiegają się na SkiaSharp, mogą zainstalowaćIronBarcode bez ostrzeżeń NU1608 lub błędów powiązań w czasie uruchomienia. Negocjacja wersji, którą wprowadzał BarcodeLib, zniknęła.
Bezpośrednie wyjście tablicy bajtów: .ToPngBinaryData() zwraca byte[] na końcu łańcucha fluent. MemoryStream pośrednik wymagany przezBarcodeLibdla wyjścia tablicy bajtów jest wyeliminowany z każdej akcji kontrolera, metody serwisowej i obsługi API generującej kody kreskowe.
Przetwarzanie kodów kreskowych PDF: BarcodeReader.Read() akceptuje pliki PDF native. Aplikacje generujące dokumenty PDF z osadzonymi kodami kreskowymi mogą odczytywać te kody bez oddzielnej biblioteki renderowania PDF. Cały łańcuch — generowanie, osadzanie PDF i czytanie — obsługiwany jest w ramach IronBarcode.
Wsparcie komercyjne i SLA:IronBarcode jest wspierany przez model wsparcia komercyjnego Iron Software z określonym tempem aktualizacji. Gdy pojawiają się nowe wydania .NET lub zmiany łamiące w ekosystemie .NET,IronBarcode publikują aktualizacje kompatybilności w harmonogramie związanym z komercyjnym SLA, a nie dostępnością społeczności.
Generowanie kodów QR bez drugiej biblioteki: QRCodeWriter obsługuje osadzanie logo, dostosowywanie kolorów i konfigurację poziomu korekcji błędów poprzez metody łańcuchowe.BarcodeLib3.x generuje tylko 1D symbologie — projekty, które potrzebowały QR obok BarcodeLib, wcześniej dodawały dodatkową bibliotekę, taką jak QRCoder. Zespoły, których wymagania dotyczące kodów QR się rozszerzyły, zyskują te funkcje w tym samym pakiecie, bez zmiany swojego przepływu generacji.
Często Zadawane Pytania
Dlaczego warto przejść z BarcodeLib na IronBarcode?
Typowe powody to uproszczenie licencjonowania (eliminacja złożoności związanej z SDK i kluczem uruchomieniowym), zniesienie limitów przepustowości, uzyskanie natywnej obsługi plików PDF, usprawnienie wdrażania w środowisku Docker/CI/CD oraz ograniczenie powtarzalnego kodu API w kodzie produkcyjnym.
Jak zastąpić wywołania API BarcodeLib za pomocą IronBarcode?
Zastąp standardowe fragmenty kodu dotyczące tworzenia instancji i licencjonowania wyrażeniem IronBarCode.License.LicenseKey = "key". Zastąp wywołania czytnika wyrażeniem BarcodeReader.Read(path), a wywołania zapisu wyrażeniem BarcodeWriter.CreateBarcode(data, encoding). Metody statyczne nie wymagają zarządzania instancjami.
Jak bardzo zmienia się kod podczas migracji z BarcodeLib do IronBarcode?
Większość migracji skutkuje zmniejszeniem liczby linii kodu. Usuwane są standardowe fragmenty dotyczące licencji, konstruktory instancji oraz jawna konfiguracja formatów. Podstawowe operacje odczytu/zapisu są mapowane na krótsze odpowiedniki w IronBarcode z bardziej przejrzystymi obiektami wynikowymi.
Czy podczas migracji muszę mieć zainstalowane zarówno BarcodeLib, jak i IronBarcode?
Nie. Większość migracji polega na bezpośredniej wymianie, a nie na równoległym działaniu. Należy migrować po jednej klasie usługowej na raz, zastąpić odwołanie do NuGet oraz zaktualizować wzorce instancjonowania i wywoływania API przed przejściem do kolejnej klasy.
Jaka jest nazwa pakietu NuGet dla IronBarcode?
Pakiet nosi nazwę „IronBarcode” (z wielkimi literami B i C). Zainstaluj go za pomocą polecenia „Install-Package IronBarcode” lub „dotnet add package IronBarcode”. Dyrektywa using w kodzie to „using IronBarcode;”.
W jaki sposób IronBarcode upraszcza wdrażanie Docker w porównaniu z BarcodeLib?
IronBarcode to pakiet NuGet bez zewnętrznych plików SDK ani konfiguracji licencji. W Dockerze należy ustawić zmienną środowiskową IRONBARCODE_LICENSE_KEY, a pakiet zajmie się weryfikacją licencji podczas uruchamiania.
Czy IronBarcode automatycznie wykrywa wszystkie formaty kodów kreskowych po migracji z BarcodeLib?
Tak. IronBarcode automatycznie wykrywa symbole we wszystkich obsługiwanych formatach. Wyraźne wyliczenie typów kodów kreskowych nie jest wymagane. Jeśli format jest już znany, a wydajność ma znaczenie, BarcodeReaderOptions pozwala ograniczyć obszar wyszukiwania w celu optymalizacji.
Czy IronBarcode może odczytywać BarCodes z plików PDF bez oddzielnej biblioteki?
Tak. BarCodeReader.Read("document.pdf") przetwarza pliki PDF natywnie. Wyniki obejmują PageNumber, Format, Value i Confidence dla każdego znalezionego kodu kreskowego. Nie jest wymagany żaden zewnętrzny etap renderowania pliku PDF.
W jaki sposób IronBarcode obsługuje równoległe przetwarzanie kodów kreskowych?
Metody statyczne IronBarcode są bezstanowe i bezpieczne dla wątków. Użyj Parallel.ForEach bezpośrednio na listach plików bez zarządzania instancjami dla poszczególnych wątków. BarcodeReaderOptions.MaxParallelThreads kontroluje wewnętrzny limit wątków.
Jakie właściwości wyników ulegają zmianie podczas migracji z BarcodeLib do IronBarcode?
Typowe zmiany nazw: BarcodeValue staje się Value, BarcodeType staje się Format. Wyniki IronBarcode zawierają również Confidence i PageNumber. Funkcja wyszukiwania i zamiany w całym rozwiązaniu obsługuje zmiany nazw w istniejącym kodzie przetwarzania wyników.
Jak skonfigurować licencjonowanie IronBarcode w potoku CI/CD?
Zapisz IronBarcode_LICENSE_KEY jako sekret potoku i przypisz IronBarCode.License.LicenseKey w kodzie uruchamiającym aplikację. Jeden sekret obejmuje wszystkie środowiska, w tym środowisko programistyczne, testowe, przejściowe i produkcyjne.
Czy IronBarcode obsługuje generowanie kodów QR z niestandardowym stylem?
Tak. Funkcja QRCodeWriter.CreateQrCode() obsługuje niestandardowe kolory za pomocą ChangeBarCodeColor(), osadzanie logo za pomocą AddBrandLogo(), konfigurowalne poziomy korekcji błędów oraz wiele formatów wyjściowych, w tym PNG, JPG, PDF i strumień.

