如何在 C# 中處理錯誤並除錯 BarCode 操作

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

條碼處理流程可能會悄無聲息地失敗,結果為零通常會被誤認為是"未偵測到條碼"。然而,諸如文件損壞、受密碼保護的 PDF 文件或格式不符等問題都可能是造成這種情況的原因。 實施適當的日誌記錄和結構化的錯誤處理可以發現這些故障並提供可操作的診斷資訊。

IronBarcode在IronBarCode.Exceptions 命名空間中提供類型化的異常層次結構、內建的日誌記錄 API 和詳細的 BarcodeResult 屬性。 這些屬性包括偵測到的格式、解碼值、頁碼以及每次成功解碼的座標。

本指南說明如何擷取和解釋類型化異常、從失敗的讀取中提取診斷上下文、啟用結構化日誌記錄以及隔離批次操作期間的故障。

快速入門:處理BarCode錯誤並啟用診斷功能

請將讀寫呼叫封裝在 try-catch 區塊中,並針對 IronBarcode 的類型化例外狀況進行處理,以顯示可採取行動的錯誤訊息,而非靜默失敗。

  1. 使用NuGet套件管理器安裝https://www.nuget.org/packages/BarCode

    PM > Install-Package BarCode
  2. 複製並運行這段程式碼。

    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. 部署到您的生產環境進行測試

    今天就在您的專案中開始使用免費試用IronBarcode

    arrow pointer

如何捕獲和解析IronBarcode異常?

從最具體到最一般,捕獲IronBarcode異常。 先處理可操作的異常(例如文件錯誤、PDF 密碼錯誤和編碼錯誤),然後再處理基本類型。 IronBarcode 的.Exceptions 命名空間定義了 11 種異常類型,每種類型對應一種特定的故障模式:

IronBarcode 例外類型 — 原因與建議的解決方案
例外類型觸發建議修正
IronBarCodeFileException檔案已損壞、被鎖定或為不支援的影像格式。驗證文件是否為受支援的影像格式且未被鎖定;同時,對於缺失的文件,單獨捕獲FileNotFoundException
IronBarCodePdfPasswordExceptionPDF 檔案受密碼保護或已加密透過 PdfBarcodeReaderOptions 提供密碼,或跳過檔案並記錄
IronBarCodeEncodingExceptionBarCode生成過程中的通用編碼錯誤驗證輸入資料是否符合目標 BarcodeWriterEncoding 的限制條件
IronBarCodeContentTooLongEncodingException內容超過所選符號集的字元限制截斷資料或切換至更高容量的格式(QR、DataMatrix)
IronBarCodeFormatOnlyAcceptsNumericValuesEncodingException傳遞至僅限數字格式的非數字字元(EAN、UPC)對輸入資料進行清理或轉換為字母數字格式(Code128、Code39)
IronBarCodeUnsupportedRendererEncodingExceptionIronBarcode 無法寫入選定的條碼編碼請使用 BarcodeWriterEncoding 枚舉,而非 BarcodeEncoding
IronBarCodeParsingException結構化資料 (GS1-128) 在解析過程中驗證失敗在解析前,請使用 Code128GS1Parser.IsValid() 驗證 GS1 結構
IronBarCodeNativeException原生互通層發生錯誤(缺少 DLL 檔案、平台不相容)請確認已安裝特定平台的 NuGet 套件(BarCode.Linux、BarCode.macOS)
IronBarCodeConfidenceThresholdException傳遞給 reader 選項的信心閾值參數無效請確保 ConfidenceThreshold 值介於 0.0 至 1.0 之間
IronBarCodeUnsupportedException當前上下文中不支援此操作請查閱變更日誌以確認您所使用版本的功能可用性
IronBarCodeException基本類型 — 擒獲上述未匹配的任何 IronBarcode 特定錯誤記錄完整的例外情況詳細資訊,並上報以進行調查

請使用 when 子句的例外篩選器,以避免深層嵌套並路由重疊的例外類型。 缺少檔案時會拋出標準的 System.IO.FileNotFoundException 錯誤,而非 IronBarCodeFileException,因此請針對此情況新增獨立的 catch 區塊:

輸入

Code128 條碼編碼發票號碼(成功路徑)和倉庫標籤條碼表示缺少 PDF 的內容(失敗路徑)。

Code128 條碼編碼 INV-2024-7829 用作掃描發票輸入
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

輸出

請注意有效檔案解析為解碼後的條碼類型和值。

控制台輸出顯示 Code128 解碼成功:[Code128] INV-2024-7829

檔案缺失會觸發 FileNotFoundException,並由專用的 catch 區塊進行處理。

控制台輸出顯示缺少 warehouse-labels.pdf 文件,並出現 FileNotFoundException 異常。

when (ex.Message.Contains("DLL")) 上的 IronBarCodeNativeException 篩選器會將缺少依賴項的錯誤導向至特定處理程序,同時不影響其他原生例外狀況。 這種方法在 Docker 部署中尤其有用,因為 Docker 部署中可能缺少特定於平台的軟體包。

當授權金鑰無效或缺失時,會另行拋出 IronSoftware.Exceptions.LicensingException 錯誤。 在應用程式啟動時捕獲此異常,而不是在單一讀取或寫入呼叫周圍捕獲。


如何從讀取失敗的資料中提取診斷詳情?

讀取操作回傳零結果也不屬於例外; 它會產生一個空的 BarcodeResults 集合。 透過檢查輸入參數、配置選項和傳回的任何部分結果來取得診斷上下文。

BarcodeResult 物件提供用於事後分析的有用屬性,包括 PageNumber 以及 Points (邊角座標)。 若出現結果但與預期不符,請先將 BarcodeType 與預期格式進行比對,並驗證 PageNumber

輸入

一個編碼了發票編號的 Code128 BARCODE,讀取時需將 ExpectBarcodeTypes 設為 Code128,並將 QRCodeReadingSpeed.Detailed 設為 ReadingSpeed.Detailed 以確保完整掃描。

Code128 條碼編碼 INV-2024-7829 用作掃描發票輸入
: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

輸出

請注意ExpectBarcodeTypes 與圖片中的 BARCODE 匹配時,讀取結果將返回類型、數值、頁碼及位置。

控制台輸出顯示 Code128 解碼成功,並顯示了頁碼和位置座標。

ExpectBarcodeTypes 未包含實際符號,讀取操作將返回空結果。 [WARN] 區塊記錄配置的類型、讀取速度以及建議的下一步操作。

控制台輸出顯示 [警告] 找不到條碼,ExpectBarcodeTypes 設定為 Code39,但對應的是 Code128 影像

診斷過程中會出現兩種常見模式。 在 ExpectBarcodeTypes 設定過於狹窄的情況下,若搜尋結果為空,通常表示該 BARCODE 採用了不同的符碼系統; 擴展至 BarcodeEncoding.All 可確認此點。 解碼結果異常通常表示影像品質較差。

應用影像濾鏡並以較慢的讀取速度重試通常可以解決這些問題。 您亦可切換 RemoveFalsePositive 選項,以消除因雜訊背景所產生的虛假讀取。

如何啟用條碼操作的詳細日誌記錄?

IronBarcode 透過 IronSoftware.Logger 提供內建的記錄 API。 在進行任何條碼操作之前,設定日誌記錄模式和檔案路徑,以擷取讀寫管道的內部診斷輸出。

輸入

啟用詳細日誌記錄時,使用 Code128 條碼 TIFF 影像作為讀取目標。

Code128 條碼編碼 PROB-SCAN-999 用作日誌記錄範例中的問題掃描輸入
: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 同時擷取除錯輸出與檔案層級的記錄。 日誌檔案記錄內部處理步驟,例如影像預處理階段、格式偵測嘗試和本機互通調用,這些步驟無法透過公用 API 查看。

對於使用結構化記錄框架(如 Serilog、NLog、Microsoft.Extensions.Logging)的生產線,將 IronBarcode 操作封裝於中介軟體層中,可在內建日誌檔之外新增結構化 JSON 條目。內建記錄器會寫入純文字診斷資訊,這些資訊對於支援升級處理非常有用; 結構化包裝器為可觀測性堆疊提供可查詢欄位。

: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

結構化輸出可直接與日誌聚合工具整合。 在容器化部署環境中,將 Pipe stdout 傳送至 Fluentd、Datadog 或 CloudWatch。 經過時間欄位可以突出顯示效能下降情況,防止其演變為服務等級協定 (SLA) 違規。

輸出

控制台輸出顯示條碼讀取成功(已啟用詳細日誌記錄),並顯示了日誌檔案路徑。

如何調試批次條碼處理?

透過將每個讀取操作隔離到其自身的 try-catch 區塊中來處理多個文件,記錄每個文件的結果,並產生匯總摘要。 即使發生故障,管道也會繼續運行,而不是在遇到第一個錯誤時停止。

輸入

來自 scans/ 批次目錄中的五張 Code128 BARCODE 圖片中的四張。 第五個檔案 (scan-05-broken.png) 包含無效位元組,將觸發檔案異常。

Code128 barcode encoding ITEM-SQ-001

第一批 — 掃描 1

Code128 barcode encoding ITEM-SQ-002

第一批 — 掃描 2

Code128 barcode encoding ITEM-SQ-003

第一批 — 掃描 3

Code128 barcode encoding ITEM-SQ-004

第一批 — 掃描 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

輸出

控制台輸出顯示批次摘要:4 個成功,1 個失敗,並包含損壞檔案的錯誤詳細資料。

執行過程中,控制台會為每個解碼的條碼輸出一行訊息,接著是包含檔案計數、成功次數、空讀取次數、失敗次數和運行時間的摘要。錯誤訊息會列出對應的檔案名稱和失敗原因。

這個過程區分三種結果類別:成功(找到並解碼條碼)、空(讀取檔案但未偵測到條碼)和失敗(拋出例外)。 這種區別很重要,因為空讀取和讀取失敗需要不同的處理方式。 空讀取可能需要更廣泛的格式設置,而失敗通常表示基礎架構問題,例如缺少檔案、資源被鎖定或缺少本地依賴項。

錯誤清單維護每個文件的上下文,以支援根本原因分析。 在 CI/CD 管道中,解析此輸出以設定退出代碼(零表示完全成功,非零表示 failCount 大於零)或將錯誤詳細資訊轉發到警報系統。

若需提升處理效能,請將 Multithreaded 設為 true 並調整 MaxParallelThreads 以配合可用 CPU 核心數,以啟用平行處理。 透過將平行迭代包裝在 Parallel.ForEach 中,並使用線程安全的集合來儲存錯誤列表,從而保持每個檔案的隔離。


延伸閱讀

當管道準備好投入生產時,請查看許可證選項

常見問題解答

How can I handle errors in barcode operations using IronBarcode?

IronBarcode provides typed exceptions and built-in logging to efficiently manage and handle errors in barcode operations, ensuring your application runs smoothly.

What features does IronBarcode offer for debugging barcode issues?

IronBarcode includes diagnostic extraction and production-ready batch error isolation, which assist developers in identifying and resolving barcode-related issues efficiently.

Can IronBarcode log errors during barcode processing?

Yes, IronBarcode has built-in logging capabilities that allow developers to capture and log error details during barcode processing, facilitating easier debugging.

What are typed exceptions in IronBarcode?

Typed exceptions in IronBarcode are specific error types that provide detailed information about barcode operation issues, making it easier for developers to diagnose and fix problems.

How does IronBarcode assist with batch error isolation?

IronBarcode offers production-ready batch error isolation, which helps in separating erroneous barcode operations from successful ones, streamlining error management in batch processing.

Is there a way to extract diagnostics from barcode operations using IronBarcode?

Yes, IronBarcode provides diagnostic extraction tools that help developers gather detailed information about barcode operations, aiding in troubleshooting and error resolution.

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。

準備好開始了嗎?
Nuget 下載 2,143,620 | 版本: 2026.4 剛剛發布
Still Scrolling Icon

還在捲動嗎?

想要快速證明? PM > Install-Package BarCode
執行範例 看您的字串變成 BarCode。