Jak radzić sobie z błędami i debugować operacje związane z kodami kreskowymi w języku C

This article was translated from English: Does it need improvement?
Translated
View the article in English

Procesy przetwarzania BarCode mogą zakończyć się niepowodzeniem bez wyświetlania komunikatu, a brak wyników jest często mylnie interpretowany jako "brak BarCode". Przyczyną mogą być jednak takie problemy, jak uszkodzone pliki, pliki PDF chronione hasłem lub niezgodności formatów. Wdrożenie odpowiedniego logowania i ustrukturyzowanego obsługi błędów pozwala wykryć te awarie i zapewnia praktyczne diagnozy.

IronBarcode oferuje typowaną hierarchię wyjątków w przestrzeni nazw IronBarCode.Exceptions, wbudowany interfejs API do logowania oraz szczegółowe właściwości BarcodeResult. Właściwości te obejmują wykryty format, zdekodowaną wartość, numer strony oraz współrzędne dla każdego pomyślnego dekodowania.

W niniejszym poradniku wyjaśniono, jak przechwytywać i interpretować wyjątki typowe, wyodrębniać kontekst diagnostyczny z nieudanych odczytów, włączać rejestrowanie strukturalne oraz izolować awarie podczas operacji wsadowych.

Szybki start: Obsługa błędów BarCode i włączanie diagnostyki

Należy otoczyć wywołania odczytu/zapisu blokami try-catch ukierunkowanymi na typowane wyjątki IronBarcode, aby wyświetlać komunikaty o błędach umożliwiające podjęcie działań zamiast cichych awarii.

  1. Install IronBarcode with NuGet Package Manager

    PM > Install-Package BarCode
  2. Skopiuj i uruchom ten fragment kodu.

    using IronBarCode;
    using IronBarCode.Exceptions;
    
    try
    {
        BarcodeResults results = BarcodeReader.Read("label.pdf");
        Console.WriteLine($"Found {results.Count} barcode(s)");
    }
    catch (IronBarCodeFileException ex)
    {
        Console.Error.WriteLine($"File error: {ex.Message}");
    }
  3. Wdrożenie do testowania w środowisku produkcyjnym

    Rozpocznij używanie IronBarcode w swoim projekcie już dziś z darmową wersją próbną

    arrow pointer

Jak wykrywać i interpretować wyjątki IronBarcode?

Przechwytuj wyjątki IronBarcode od najbardziej szczegółowych do najbardziej ogólnych. Bloki catch należy uporządkować tak, aby najpierw obsługiwały wyjątki wymagające podjęcia działań, takie jak błędy plików, haseł PDF i kodowania, a następnie wyjątki typu podstawowego. Przestrzeń nazw IronBarCode.Exceptions definiuje 11 typów wyjątków, z których każdy odpowiada konkretnemu trybowi awarii:

Typy wyjątków IronBarcode — przyczyny i zalecane rozwiązania
Typ wyjątkuWyzwalaczZalecana poprawka
IronBarCodeFileExceptionPlik jest uszkodzony, zablokowany lub ma nieobsługiwany format obrazuSprawdź, czy plik ma obsługiwany format obrazu i nie jest zablokowany; oddzielnie przechwytuj wyjątki FileNotFoundException dla brakujących plików
IronBarCodePdfPasswordExceptionPlik PDF jest chroniony hasłem lub zaszyfrowanyPodaj hasło za pomocą PdfBarcodeReaderOptions lub pomiń plik i zaloguj się
IronBarCodeEncodingExceptionOgólny błąd kodowania podczas generowania BarCodeSprawdź, czy dane wejściowe są zgodne z ograniczeniami docelowego BarcodeWriterEncoding
IronBarCodeContentTooLongEncodingExceptionWartość przekracza limit znaków dla wybranej symbolikiSkróć dane lub przejdź na format o większej pojemności (QR, DataMatrix)
IronBarCodeFormatOnlyAcceptsNumericValuesEncodingExceptionZnaki nienumeryczne przekształcone do formatu wyłącznie numerycznego (EAN, UPC)Oczyść dane wejściowe lub przełącz na format alfanumeryczny (Code128, Code39)
IronBarCodeUnsupportedRendererEncodingExceptionWybrany kod kreskowy nie jest zapisywalny przez IronBarcodeZastosuj wyliczenie BarcodeWriterEncoding zamiast BarcodeEncoding
IronBarCodeParsingExceptionDane strukturalne (GS1-128) nie przechodzą walidacji podczas parsowaniaPrzed parsowaniem należy zweryfikować strukturę GS1 za pomocą funkcji Code128GS1Parser.IsValid().
IronBarCodeNativeExceptionBłąd w natywnej warstwie interoperacyjności (brakujące biblioteki DLL, niezgodność platform)Sprawdź, czy zainstalowane są pakiety NuGet specyficzne dla danej platformy (BarCode.Linux, BarCode.macOS)
IronBarCodeConfidenceThresholdExceptionPrzekazano nieprawidłowy argument progu pewności do opcji czytnikaUpewnij się, że wartość ConfidenceThreshold mieści się w przedziale od 0,0 do 1,0
IronBarCodeUnsupportedExceptionOperacja nieobsługiwana w bieżącym kontekścieSprawdź dziennik zmian, aby dowiedzieć się, które funkcje są dostępne w Twojej wersji
IronBarCodeExceptionTyp bazowy — przechwytuje wszelkie błędy specyficzne dla IronBarcode, które nie zostały dopasowane powyżejRejestruj pełne szczegóły wyjątków i eskaluj je do dalszego zbadania

Użyj filtrów wyjątków z klauzulami when, aby kierować pokrywające się typy wyjątków bez głębokiego zagnieżdżenia. Brakujące pliki rzucają standardowy System.IO.FileNotFoundException zamiast IronBarCodeFileException, więc zawrzyj osobny blok catch dla tego przypadku:

Dane wejściowe

Kod kreskowy Code128 zawierający numer faktury (ścieżka sukcesu) oraz kod kreskowy etykiety magazynowej przedstawiający zawartość brakującego pliku PDF (ścieżka niepowodzenia).

BarCode Code128 o kodzie INV-2024-7829 używany jako skanowana faktura wejściowa
Code128 barcode representing the content of the missing warehouse-labels.pdf failure path input
:path=/static-assets/barcode/content-code-examples/how-to/detailed-error-messages/exception-hierarchy.cs
using IronBarCode;
using IronBarCode.Exceptions;

// Success path: valid file present on disk
string filePath = "scanned-invoice.png";
// Failure path: file does not exist → caught by FileNotFoundException below
// string filePath = "warehouse-labels.pdf";

try
{
    BarcodeResults results = BarcodeReader.Read(filePath);
    foreach (BarcodeResult result in results)
    {
        // Print the detected symbology and decoded value for each barcode found
        Console.WriteLine($"[{result.BarcodeType}] {result.Value}");
    }
}
catch (IronBarCodePdfPasswordException ex)
{
    // PDF is encrypted — supply the password via PdfBarcodeReaderOptions before retrying
    Console.Error.WriteLine($"PDF requires password: {filePath} — {ex.Message}");
}
catch (IronBarCodeFileException ex)
{
    // File is present but corrupted, locked, or in an unsupported format
    Console.Error.WriteLine($"Cannot read file: {filePath} — {ex.Message}");
}
catch (FileNotFoundException ex)
{
    // Missing files throw FileNotFoundException, not IronBarCodeFileException
    Console.Error.WriteLine($"File not found: {filePath} — {ex.Message}");
}
catch (IronBarCodeNativeException ex) when (ex.Message.Contains("DLL"))
{
    // The when filter routes only missing-DLL errors here; other native exceptions
    // fall through to the IronBarCodeException block below
    Console.Error.WriteLine($"Missing native dependency: {ex.Message}");
}
catch (IronBarCodeException ex)
{
    // Base catch for any IronBarcode-specific error not matched by the blocks above
    Console.Error.WriteLine($"IronBarcode error: {ex.GetType().Name} — {ex.Message}");
}
Imports IronBarCode
Imports IronBarCode.Exceptions

' Success path: valid file present on disk
Dim filePath As String = "scanned-invoice.png"
' Failure path: file does not exist → caught by FileNotFoundException below
' Dim filePath As String = "warehouse-labels.pdf"

Try
    Dim results As BarcodeResults = BarcodeReader.Read(filePath)
    For Each result As BarcodeResult In results
        ' Print the detected symbology and decoded value for each barcode found
        Console.WriteLine($"[{result.BarcodeType}] {result.Value}")
    Next
Catch ex As IronBarCodePdfPasswordException
    ' PDF is encrypted — supply the password via PdfBarcodeReaderOptions before retrying
    Console.Error.WriteLine($"PDF requires password: {filePath} — {ex.Message}")
Catch ex As IronBarCodeFileException
    ' File is present but corrupted, locked, or in an unsupported format
    Console.Error.WriteLine($"Cannot read file: {filePath} — {ex.Message}")
Catch ex As FileNotFoundException
    ' Missing files throw FileNotFoundException, not IronBarCodeFileException
    Console.Error.WriteLine($"File not found: {filePath} — {ex.Message}")
Catch ex As IronBarCodeNativeException When ex.Message.Contains("DLL")
    ' The when filter routes only missing-DLL errors here; other native exceptions
    ' fall through to the IronBarCodeException block below
    Console.Error.WriteLine($"Missing native dependency: {ex.Message}")
Catch ex As IronBarCodeException
    ' Base catch for any IronBarcode-specific error not matched by the blocks above
    Console.Error.WriteLine($"IronBarcode error: {ex.GetType().Name} — {ex.Message}")
End Try
$vbLabelText   $csharpLabel

Wynik

Zwróć uwagęPrawidłowy plik odpowiada zdekodowanemu typowi i wartości BarCODE.

Wynik wyświetlony w konsoli po pomyślnym zdekodowaniu Code128: [Code128] INV-2024-7829

Brakujący plik wywołuje FileNotFoundException, kierowany przez dedykowany blok catch.

Wynik konsoli pokazujący wyjątek FileNotFoundException dla brakującego pliku warehouse-labels.PDF

Filtr when (ex.Message.Contains("DLL")) na IronBarCodeNativeException kieruje błędy brakujących zależności do określonego obsługującego, bez wpływu na inne wyjątki natywne. Takie podejście jest szczególnie przydatne w przypadku wdrożeń Docker, gdzie mogą brakować pakietów specyficznych dla danej platformy.

IronSoftware.Exceptions.LicensingException jest rzucany osobno, gdy klucz licencyjny jest nieprawidłowy lub brakujący. Wyłapuj ten wyjątek podczas uruchamiania aplikacji, a nie w trakcie poszczególnych wywołań odczytu lub zapisu.


Jak wyodrębnić szczegóły diagnostyczne z nieudanych odczytów?

Operacja odczytu, która zwraca zero wyników, nie jest wyjątkiem; produkuje pustą kolekcję BarcodeResults. Kontekst diagnostyczny uzyskuje się poprzez analizę parametrów wejściowych, skonfigurowanych opcji oraz wszelkich zwracanych wyników częściowych.

Obiekt BarcodeResult dostarcza właściwości użyteczne do analizy pośmiertnej, w tym BarcodeType, Value, PageNumber i Points (współrzędne narożników). Jeśli wyniki są obecne, ale nieoczekiwane, najpierw sprawdź BarcodeType względem oczekiwanego formatu i zweryfikuj PageNumber.

Dane wejściowe

Kod kreskowy Code128 kodujący numer faktury, odczytany z ExpectBarcodeTypes ustawionym na Code128 i QRCode oraz ReadingSpeed.Detailed dla dokładnego skanowania.

BarCode Code128 o kodzie INV-2024-7829 używany jako skanowana faktura wejściowa
:path=/static-assets/barcode/content-code-examples/how-to/detailed-error-messages/diagnostic-logging.cs
using IronBarCode;

string filePath = "scanned-invoice.png";

// Configure the reader to narrow the search to specific symbologies and use
// a thorough scan pass — narrows false positives and improves decode accuracy
var options = new BarcodeReaderOptions
{
    ExpectBarcodeTypes = BarcodeEncoding.Code128 | BarcodeEncoding.QRCode, // limit scan to known formats
    Speed = ReadingSpeed.Detailed,      // slower but more thorough — use ExtremeDetail for damaged images
    ExpectMultipleBarcodes = true       // scan the full image rather than stopping at the first match
};

BarcodeResults results = BarcodeReader.Read(filePath, options);

// An empty result is not an exception — it means no barcode matched the configured options
if (results == null || results.Count == 0)
{
    // Log the configured options alongside the warning so the cause is immediately actionable
    Console.Error.WriteLine($"[WARN] No barcodes found in: {filePath}");
    Console.Error.WriteLine($"  ExpectedTypes: {options.ExpectBarcodeTypes}");
    Console.Error.WriteLine($"  Speed: {options.Speed}");
    Console.Error.WriteLine($"  Action: Retry with ReadingSpeed.ExtremeDetail or broaden ExpectBarcodeTypes");
}
else
{
    foreach (BarcodeResult result in results)
    {
        // Points contains the four corner coordinates of the barcode in the image;
        // use the first corner as a representative position indicator
        string pos = result.Points.Length > 0 ? $"{result.Points[0].X:F0},{result.Points[0].Y:F0}" : "N/A";
        Console.WriteLine($"[{result.BarcodeType}] {result.Value} "
            + $"(Page: {result.PageNumber}, Position: {pos})");
    }
}
Imports IronBarCode

Dim filePath As String = "scanned-invoice.png"

' Configure the reader to narrow the search to specific symbologies and use
' a thorough scan pass — narrows false positives and improves decode accuracy
Dim options As New BarcodeReaderOptions With {
    .ExpectBarcodeTypes = BarcodeEncoding.Code128 Or BarcodeEncoding.QRCode, ' limit scan to known formats
    .Speed = ReadingSpeed.Detailed,      ' slower but more thorough — use ExtremeDetail for damaged images
    .ExpectMultipleBarcodes = True       ' scan the full image rather than stopping at the first match
}

Dim results As BarcodeResults = BarcodeReader.Read(filePath, options)

' An empty result is not an exception — it means no barcode matched the configured options
If results Is Nothing OrElse results.Count = 0 Then
    ' Log the configured options alongside the warning so the cause is immediately actionable
    Console.Error.WriteLine($"[WARN] No barcodes found in: {filePath}")
    Console.Error.WriteLine($"  ExpectedTypes: {options.ExpectBarcodeTypes}")
    Console.Error.WriteLine($"  Speed: {options.Speed}")
    Console.Error.WriteLine($"  Action: Retry with ReadingSpeed.ExtremeDetail or broaden ExpectBarcodeTypes")
Else
    For Each result As BarcodeResult In results
        ' Points contains the four corner coordinates of the barcode in the image;
        ' use the first corner as a representative position indicator
        Dim pos As String = If(result.Points.Length > 0, $"{result.Points(0).X:F0},{result.Points(0).Y:F0}", "N/A")
        Console.WriteLine($"[{result.BarcodeType}] {result.Value} " &
                          $"(Page: {result.PageNumber}, Position: {pos})")
    Next
End If
$vbLabelText   $csharpLabel

Wynik

Zwróć uwagęKiedy ExpectBarcodeTypes odpowiada kodowi kreskowemu w obrazie, odczyt zwraca typ, wartość, numer strony i pozycję.

Wynik konsoli pokazujący pomyślne zdekodowanie Code128 wraz z numerem strony i współrzędnymi pozycji

Jeśli ExpectBarcodeTypes nie zawiera faktycznej symbologii, odczyt zwraca pusty wynik. Blok [WARN] rejestruje skonfigurowane typy, prędkość odczytu oraz sugerowane dalsze działanie.

Wynik konsoli pokazujący [WARN] brak znalezionych BarCode'ów przy ustawieniu ExpectBarcodeTypes na Code39 dla obrazu Code128

Podczas diagnostyki pojawiają się dwa typowe wzorce. Puste wyniki z wąskim ustawieniem ExpectBarcodeTypes często oznaczają, że kod kreskowy używa innej symbologii; rozszerzenie do BarcodeEncoding.All może to potwierdzić. Nieoczekiwane wyniki dekodowania zazwyczaj wskazują na niską jakość obrazu.

Zastosowanie filtrów obrazu i ponowna próba przy mniejszej prędkości czytania często rozwiązuje te problemy. Można również przełączyć opcję RemoveFalsePositive, aby wyeliminować fałszywe odczyty z hałaśliwych tła.

Jak włączyć szczegółowe logowanie dla operacji związanych z kodami kreskowymi BarCode?

IronBarcode udostępnia wbudowane API do logowania przez IronSoftware.Logger. Przed rozpoczęciem jakichkolwiek operacji związanych z kodami kreskowymi należy ustawić tryb logowania i ścieżkę do pliku, aby przechwycić wewnętrzne dane diagnostyczne z potoków odczytu i zapisu.

Dane wejściowe

Obraz TIFF z kodem barcode Code128 używany jako cel odczytu przy włączonym szczegółowym logowaniu.

BarCode Code128 w formacie PROB-SCAN-999 użyty jako dane wejściowe do skanowania w przykładzie rejestrowania
:path=/static-assets/barcode/content-code-examples/how-to/detailed-error-messages/enable-logging.cs
using IronBarCode;

// Enable IronBarcode's built-in logging — set BEFORE any read/write calls
// LoggingModes.All writes both debug output and file-level diagnostics
IronSoftware.Logger.LoggingMode = IronSoftware.Logger.LoggingModes.All;
IronSoftware.Logger.LogFilePath = "ironbarcode-debug.log"; // path is relative to the working directory

// All subsequent operations will write internal processing steps to the log file:
// image pre-processing stages, format detection attempts, and native interop calls
var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Detailed,
    ExpectBarcodeTypes = BarcodeEncoding.All  // scan for every supported symbology
};

BarcodeResults results = BarcodeReader.Read("problem-scan.tiff", options);
Console.WriteLine($"Read complete. Results: {results.Count}. See ironbarcode-debug.log for details.");
Imports IronBarCode

' Enable IronBarcode's built-in logging — set BEFORE any read/write calls
' LoggingModes.All writes both debug output and file-level diagnostics
IronSoftware.Logger.LoggingMode = IronSoftware.Logger.LoggingModes.All
IronSoftware.Logger.LogFilePath = "ironbarcode-debug.log" ' path is relative to the working directory

' All subsequent operations will write internal processing steps to the log file:
' image pre-processing stages, format detection attempts, and native interop calls
Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Detailed,
    .ExpectBarcodeTypes = BarcodeEncoding.All  ' scan for every supported symbology
}

Dim results As BarcodeResults = BarcodeReader.Read("problem-scan.tiff", options)
Console.WriteLine($"Read complete. Results: {results.Count}. See ironbarcode-debug.log for details.")
$vbLabelText   $csharpLabel

LoggingModes.All przechwytuje zarówno dane wyjściowe debugowania, jak i logi na poziomie plików. Plik dziennika rejestruje wewnętrzne etapy przetwarzania, takie jak etapy wstępnego przetwarzania obrazów, próby wykrywania formatu oraz natywne wywołania interoperacyjne, które nie są widoczne za pośrednictwem publicznego interfejsu API.

Dla produkcyjnych potoków używających strukturalnego frameworka logowania (Serilog, NLog, Microsoft.Extensions.Logging), opakowanie operacji IronBarcode w warstwę pośrednią dodaje strukturalne wpisy JSON obok wbudowanego logu. Wbudowany logger zapisuje diagnostykę w postaci zwykłego tekstu przydatnego do eskalacji wsparcia; Strukturalna otoczka zapewnia pola umożliwiające wyszukiwanie dla stosu obserwowalności.

:path=/static-assets/barcode/content-code-examples/how-to/detailed-error-messages/structured-wrapper.cs
using IronBarCode;
using System.Diagnostics;

// Lightweight wrapper that adds structured JSON observability to every read call.
// Call this in place of BarcodeReader.Read wherever elapsed-time and status logging is needed.
BarcodeResults ReadWithDiagnostics(string filePath, BarcodeReaderOptions options)
{
    var sw = Stopwatch.StartNew(); // start timing before the read so setup overhead is included
    try
    {
        BarcodeResults results = BarcodeReader.Read(filePath, options);
        sw.Stop();
        // Emit a structured success entry to stdout — pipe to Fluentd, Datadog, or CloudWatch
        Console.WriteLine($"{{\"file\":\"{filePath}\",\"status\":\"ok\","
            + $"\"count\":{results.Count},\"elapsed_ms\":{sw.ElapsedMilliseconds}}}");
        return results;
    }
    catch (Exception ex)
    {
        sw.Stop();
        // Emit a structured error entry to stderr with exception type, message, and elapsed time
        Console.Error.WriteLine($"{{\"file\":\"{filePath}\",\"status\":\"error\","
            + $"\"exception\":\"{ex.GetType().Name}\",\"message\":\"{ex.Message}\","
            + $"\"elapsed_ms\":{sw.ElapsedMilliseconds}}}");
        throw; // rethrow so the caller's catch blocks still handle the exception normally
    }
}
Imports IronBarCode
Imports System.Diagnostics

' Lightweight wrapper that adds structured JSON observability to every read call.
' Call this in place of BarcodeReader.Read wherever elapsed-time and status logging is needed.
Function ReadWithDiagnostics(filePath As String, options As BarcodeReaderOptions) As BarcodeResults
    Dim sw As Stopwatch = Stopwatch.StartNew() ' start timing before the read so setup overhead is included
    Try
        Dim results As BarcodeResults = BarcodeReader.Read(filePath, options)
        sw.Stop()
        ' Emit a structured success entry to stdout — pipe to Fluentd, Datadog, or CloudWatch
        Console.WriteLine($"{{""file"":""{filePath}"",""status"":""ok"",""count"":{results.Count},""elapsed_ms"":{sw.ElapsedMilliseconds}}}")
        Return results
    Catch ex As Exception
        sw.Stop()
        ' Emit a structured error entry to stderr with exception type, message, and elapsed time
        Console.Error.WriteLine($"{{""file"":""{filePath}"",""status"":""error"",""exception"":""{ex.GetType().Name}"",""message"":""{ex.Message}"",""elapsed_ms"":{sw.ElapsedMilliseconds}}}")
        Throw ' rethrow so the caller's catch blocks still handle the exception normally
    End Try
End Function
$vbLabelText   $csharpLabel

Strukturalny wynik integruje się bezpośrednio z narzędziami do agregacji logów. Przekaż stdout do Fluentd, Datadog lub CloudWatch w wdrożeniu konteneryzowanym. Pole czasu, który upłynął, wskazuje spadki wydajności, zanim staną się naruszeniami SLA.

Wynik

Wynik konsoli pokazujący pomyślne odczytanie kodu kreskowego przy włączonym szczegółowym logowaniu oraz ścieżka do pliku logu

Jak debugować przetwarzanie partii BarCode'ów?

Przetwarzaj wiele plików, izolując każdy odczyt w osobnym bloku try-catch, rejestrując wyniki dla każdego pliku i generując zbiorcze podsumowanie. Pipeline kontynuuje działanie pomimo wystąpienia błędów, zamiast zatrzymywać się przy pierwszym błędzie.

Dane wejściowe

Cztery z pięciu obrazów kodów kreskowych Code128 z katalogu seryjnego scans/. Piąty plik (scan-05-broken.png) zawiera nieprawidłowe bajty, aby wywołać wyjątek pliku.

Code128 barcode encoding ITEM-SQ-001

Partia 1 — Skan 1

Code128 barcode encoding ITEM-SQ-002

Partia 1 — Skan 2

Code128 barcode encoding ITEM-SQ-003

Partia 1 — Skan 3

Code128 barcode encoding ITEM-SQ-004

Partia 1 — Skan 4

:path=/static-assets/barcode/content-code-examples/how-to/detailed-error-messages/batch-processing.cs
using IronBarCode;
using IronBarCode.Exceptions;
using System.Diagnostics;

// Enable built-in logging for the entire batch run so internal processing steps
// are captured in the log file alongside the per-file console output
IronSoftware.Logger.LoggingMode = IronSoftware.Logger.LoggingModes.All;
IronSoftware.Logger.LogFilePath = "batch-run.log";

// Collect all files in the directory — SearchOption.TopDirectoryOnly skips subdirectories
string[] files = Directory.GetFiles("scans/", "*.*", SearchOption.TopDirectoryOnly);

var options = new BarcodeReaderOptions
{
    Speed = ReadingSpeed.Balanced,                                    // balances throughput vs accuracy
    ExpectBarcodeTypes = BarcodeEncoding.Code128 | BarcodeEncoding.QRCode, // limit to known formats
    ExpectMultipleBarcodes = true                                     // scan each file fully
};

// Three outcome counters: success (decoded), empty (read OK but no barcode found), fail (exception)
int successCount = 0;
int failCount = 0;
int emptyCount = 0;
var errors = new List<(string File, string Error)>(); // per-file error context for root cause analysis
var sw = Stopwatch.StartNew();

foreach (string file in files)
{
    try
    {
        BarcodeResults results = BarcodeReader.Read(file, options);

        // Empty result is not an exception — the file was read but contained no matching barcode
        if (results == null || results.Count == 0)
        {
            emptyCount++;
            errors.Add((file, "No barcodes detected")); // record so caller can adjust options
            continue;
        }

        foreach (BarcodeResult result in results)
        {
            Console.WriteLine($"{Path.GetFileName(file)} | {result.BarcodeType} | {result.Value}");
        }
        successCount++;
    }
    catch (IronBarCodePdfPasswordException)
    {
        // PDF is password-protected — supply password via PdfBarcodeReaderOptions to recover
        failCount++;
        errors.Add((file, "Password-protected PDF"));
    }
    catch (IronBarCodeFileException ex)
    {
        // File is corrupted, locked, or in an unsupported image format
        failCount++;
        errors.Add((file, $"File error: {ex.Message}"));
    }
    catch (FileNotFoundException ex)
    {
        // File was in the directory listing but deleted before the read completed (race condition)
        failCount++;
        errors.Add((file, $"File not found: {ex.Message}"));
    }
    catch (IronBarCodeException ex)
    {
        // Catch-all for any other IronBarcode-specific errors not handled above
        failCount++;
        errors.Add((file, $"{ex.GetType().Name}: {ex.Message}"));
    }
    catch (Exception ex)
    {
        // Unexpected non-IronBarcode error — log the full type for investigation
        failCount++;
        errors.Add((file, $"Unexpected: {ex.GetType().Name}: {ex.Message}"));
    }
}

sw.Stop();

// Summary report — parse failCount > 0 in CI/CD to set a non-zero exit code
Console.WriteLine("\n--- Batch Summary ---");
Console.WriteLine($"Total files:    {files.Length}");
Console.WriteLine($"Success:        {successCount}");
Console.WriteLine($"Empty reads:    {emptyCount}");
Console.WriteLine($"Failures:       {failCount}");
Console.WriteLine($"Elapsed:        {sw.Elapsed.TotalSeconds:F1}s");

if (errors.Any())
{
    Console.WriteLine("\n--- Error Details ---");
    foreach (var (errorFile, errorMsg) in errors)
    {
        Console.Error.WriteLine($"  {Path.GetFileName(errorFile)}: {errorMsg}");
    }
}
Imports IronBarCode
Imports IronBarCode.Exceptions
Imports System.Diagnostics

' Enable built-in logging for the entire batch run so internal processing steps
' are captured in the log file alongside the per-file console output
IronSoftware.Logger.LoggingMode = IronSoftware.Logger.LoggingModes.All
IronSoftware.Logger.LogFilePath = "batch-run.log"

' Collect all files in the directory — SearchOption.TopDirectoryOnly skips subdirectories
Dim files As String() = Directory.GetFiles("scans/", "*.*", SearchOption.TopDirectoryOnly)

Dim options As New BarcodeReaderOptions With {
    .Speed = ReadingSpeed.Balanced,                                    ' balances throughput vs accuracy
    .ExpectBarcodeTypes = BarcodeEncoding.Code128 Or BarcodeEncoding.QRCode, ' limit to known formats
    .ExpectMultipleBarcodes = True                                     ' scan each file fully
}

' Three outcome counters: success (decoded), empty (read OK but no barcode found), fail (exception)
Dim successCount As Integer = 0
Dim failCount As Integer = 0
Dim emptyCount As Integer = 0
Dim errors As New List(Of (File As String, Error As String))() ' per-file error context for root cause analysis
Dim sw As Stopwatch = Stopwatch.StartNew()

For Each file As String In files
    Try
        Dim results As BarcodeResults = BarcodeReader.Read(file, options)

        ' Empty result is not an exception — the file was read but contained no matching barcode
        If results Is Nothing OrElse results.Count = 0 Then
            emptyCount += 1
            errors.Add((file, "No barcodes detected")) ' record so caller can adjust options
            Continue For
        End If

        For Each result As BarcodeResult In results
            Console.WriteLine($"{Path.GetFileName(file)} | {result.BarcodeType} | {result.Value}")
        Next
        successCount += 1
    Catch ex As IronBarCodePdfPasswordException
        ' PDF is password-protected — supply password via PdfBarcodeReaderOptions to recover
        failCount += 1
        errors.Add((file, "Password-protected PDF"))
    Catch ex As IronBarCodeFileException
        ' File is corrupted, locked, or in an unsupported image format
        failCount += 1
        errors.Add((file, $"File error: {ex.Message}"))
    Catch ex As FileNotFoundException
        ' File was in the directory listing but deleted before the read completed (race condition)
        failCount += 1
        errors.Add((file, $"File not found: {ex.Message}"))
    Catch ex As IronBarCodeException
        ' Catch-all for any other IronBarcode-specific errors not handled above
        failCount += 1
        errors.Add((file, $"{ex.GetType().Name}: {ex.Message}"))
    Catch ex As Exception
        ' Unexpected non-IronBarcode error — log the full type for investigation
        failCount += 1
        errors.Add((file, $"Unexpected: {ex.GetType().Name}: {ex.Message}"))
    End Try
Next

sw.Stop()

' Summary report — parse failCount > 0 in CI/CD to set a non-zero exit code
Console.WriteLine(vbCrLf & "--- Batch Summary ---")
Console.WriteLine($"Total files:    {files.Length}")
Console.WriteLine($"Success:        {successCount}")
Console.WriteLine($"Empty reads:    {emptyCount}")
Console.WriteLine($"Failures:       {failCount}")
Console.WriteLine($"Elapsed:        {sw.Elapsed.TotalSeconds:F1}s")

If errors.Any() Then
    Console.WriteLine(vbCrLf & "--- Error Details ---")
    For Each errorDetail In errors
        Console.Error.WriteLine($"  {Path.GetFileName(errorDetail.File)}: {errorDetail.Error}")
    Next
End If
$vbLabelText   $csharpLabel

Wynik

Wynik konsoli pokazujący podsumowanie partii: 4 operacje zakończone sukcesem, 1 niepowodzenie, wraz ze szczegółami błędu dla uszkodzonego pliku

Podczas wykonywania konsola wyświetla jedną linię dla każdego zdekodowanego BARCODE'a, a następnie podsumowanie zawierające liczbę plików, operacje zakończone powodzeniem, puste odczyty, operacje zakończone niepowodzeniem oraz czas, który upłynął. Błędy są wymienione wraz z odpowiadającymi im nazwami plików i przyczynami niepowodzenia.

Proces rozróżnia trzy kategorie wyników: sukces (znaleziono i zdekodowano kody kreskowe), pusty (odczytano plik, ale nie wykryto kodów kreskowych) oraz niepowodzenie (wygenerowano wyjątek). To rozróżnienie ma znaczenie, ponieważ puste odczyty i awarie wymagają różnych reakcji. Puste odczyty mogą wymagać szerszych ustawień formatu, podczas gdy błędy często wskazują na problemy infrastrukturalne, takie jak brakujące pliki, zablokowane zasoby lub brakujące zależności natywne.

Lista błędów zachowuje kontekst dla poszczególnych plików, aby ułatwić analizę przyczyn źródłowych. W potoku CI/CD należy przeanalizować ten wynik w celu ustawienia kodów wyjścia (zero dla pełnego sukcesu i wartość niezerowa, gdy failCount jest większy od zera) lub przekazania szczegółów błędu do systemu alertów.

Dla wyższej przepustowości włącz przetwarzanie równoległe, ustawiając Multithreaded na true i dostosowując MaxParallelThreads do dostępnych rdzeni CPU. Zachowaj izolację poszczególnych plików, otaczając iterację równoległą w Parallel.ForEach i używając kolekcji bezpiecznej dla wątków dla listy błędów.


Więcej informacji

Zapoznaj się z opcjami licencyjnymi, gdy potok będzie gotowy do produkcji.

Często Zadawane Pytania

Jak moge obslugiwac bledy w operacjach kodow kreskowych za pomoca IronBarcode?

IronBarcode oferuje typowane wyjatki i wbudowane logowanie w celu efektywnego zarzadzania i obslugi bledow w operacjach kodow kreskowych, zapewniajac gladkie dzialanie aplikacji.

Jakie funkcje oferuje IronBarcode dla debugowania problemow z kodami kreskowymi?

IronBarcode zawiera narzedzia do ekstrakcji diagnostycznej i gotowa do produkcji izolacje bledow w partiach, ktore pomagaja deweloperom w identyfikowaniu i rozwiazywaniu problemow z kodami kreskowymi.

Czy IronBarcode moze logowac bledy podczas przetwarzania kodow kreskowych?

Tak, IronBarcode ma wbudowane mozliwosci logowania, ktore pozwalaja deweloperom na rejestrowanie i logowanie szczegolow bledow podczas przetwarzania kodow kreskowych, ulatwiajac debugowanie.

Czym sa typowane wyjatki w IronBarcode?

Typowane wyjatki w IronBarcode to specyficzne typy bledow, ktore dostarczaja szczegolowych informacji o problemach z operacjami kodow kreskowych, co ulatwia deweloperom diagnozowanie i naprawianie problemow.

Jak IronBarcode pomaga w izolacji bledow w partiach?

IronBarcode oferuje gotowa do produkcji izolacje bledow w partiach, ktora pomaga w odseparowywaniu blednych operacji kodow kreskowych od udanych, usprawniajac zarzadzanie bledami w przetwarzaniu partii.

Czy istnieje sposob na ekstrakcje diagnostyki z operacji kodow kreskowych przy uzyciu IronBarcode?

Tak, IronBarcode dostarcza narzedzia do ekstrakcji diagnostycznej, ktore pomagaja deweloperom zbierac szczegolowe informacje o operacjach kodow kreskowych, wspierajac identyfikacje i rozwiazywanie bledow.

Curtis Chau
Autor tekstów technicznych

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

Czytaj więcej
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 2,145,441 | Wersja: 2026.4 just released
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package BarCode
uruchom przykład zobacz, jak twoje ciągi zamieniają się w kody kreskowe.