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

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

BarCode 處理流程可能發生無聲失敗,此時零結果常被誤判為"未偵測到 BarCode"。然而,實際原因可能是檔案損毀、受密碼保護的 PDF 檔案,或是格式不符等問題所致。 透過實施適當的記錄機制與結構化錯誤處理,可揭露這些故障並提供可執行的診斷資訊。

IronBarcode 在 IronBarCode.Exceptions 命名空間中提供具型別的例外情況層級結構、內建的記錄 API,以及詳盡的 BarcodeResult 屬性。 這些屬性包含每次成功解碼所偵測到的格式、解碼後的值、頁碼以及座標。

本操作指南說明如何擷取並解析類型化例外狀況、從讀取失敗中提取診斷背景資訊、啟用結構化記錄,以及在批次操作期間隔離故障。

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

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

  1. using 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 的所有例外情況。 請將 catch 區塊依優先順序排列,優先處理可處理的例外狀況(例如檔案、PDF 密碼及編碼錯誤),再處理基礎類型。 IronBarCode.Exceptions 命名空間定義了 11 種例外類型,每種都對應於特定的失敗模式:

IronBarcode 例外類型 — 原因與建議的解決方案
例外類型觸發建議修正
IronBarCodeFileException檔案已損毀、被鎖定,或採用不支援的圖像格式驗證檔案是否為受支援的圖像格式且未被鎖定;此外,針對缺失的檔案應另行處理 FileNotFoundException 異常
IronBarCodePdfPasswordExceptionPDF 檔案受密碼保護或已加密透過 PdfBarcodeReaderOptions 提供密碼,或跳過檔案並記錄
IronBarCodeEncodingExceptionBarCode生成過程中的通用編碼錯誤驗證輸入資料是否符合目標 BarcodeWriterEncoding 的限制條件
IronBarCodeContentTooLongEncodingException內容超過所選符號集的字元限制截斷資料或切換至更高容量的格式(QR、DataMatrix)
IronBarCodeFormatOnlyAcceptsNumericValuesEncodingException傳遞至僅限數字格式的非數字字元(EAN、UPC)對輸入資料進行清理,或轉換為字母數字格式(Code128、Code39)
IronBarCodeUnsupportedRendererEncodingExceptionIronBarcode 無法寫入選定的 BarcodeEncoding請使用 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 BARCODE(成功路徑),以及一個代表遺失 PDF 內容的倉庫標籤 BARCODE(失敗路徑)。

作為掃描發票輸入使用的 Code128 BARCODE編碼 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

輸出

請注意有效的檔案會解析為解碼後的BARCODE類型與數值。

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

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

控制台輸出顯示因缺少 warehouse-labels.PDF 檔案而引發的 FileNotFoundException

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

當授權金鑰無效或缺失時,系統會另行拋出 IronSoftware.Exceptions.LicensingException 錯誤。 請在應用程式啟動時擒獲此例外狀況,而非在個別讀取或寫入呼叫時處理。


如何從讀取失敗中擷取診斷詳細資訊?

返回零結果的讀取操作並非例外; 它會產生一個空的 BarcodeResults 集合。 診斷背景是透過檢查輸入參數、設定選項以及任何返回的部分結果來獲取的。

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

輸入

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

作為掃描發票輸入使用的 Code128 BARCODE編碼 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] 區塊會記錄已設定的類型、讀取速度以及建議的下一步行動。

控制台輸出顯示 [WARN] 未找到 BARCODE,當 ExpectBarcodeTypes 設定為 Code39 時,處理 Code128 圖像

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

通常透過套用影像濾鏡並以較慢的讀取速度重新嘗試,即可解決這些問題。 您亦可切換 RemoveFalsePositive 選項,以消除雜訊背景造成的虛假讀取。

如何啟用BarCode操作的詳細記錄功能?

IronBarcode 透過 IronSoftware.Logger 提供內建的記錄 API。 在執行任何BarCode操作之前,請先設定記錄模式與檔案路徑,以便擷取讀取與寫入處理流程中的內部診斷輸出。

輸入

當詳細記錄功能啟用時,用作讀取目標的 Code128 BarCode TIFF 影像。

用作記錄範例問題掃描輸入的 Code128 BARCODE 編碼 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

結構化輸出可直接與日誌彙總工具整合。 在容器化部署環境中,將 stdout 傳送至 Fluentd、Datadog 或 CloudWatch。 "耗時"欄位可在性能退化演變為 SLA 違規之前,即早預警。

輸出

控制台輸出,顯示在啟用詳細記錄的情況下成功讀取BarCode,並包含日誌檔案路徑

如何除錯批次BarCode處理?

透過將每次讀取操作隔離在獨立的 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 項失敗,並附有損壞檔案的錯誤詳細資訊

執行期間,主控台會針對每個解碼的BARCODE輸出一行,隨後顯示包含檔案數、成功次數、空讀取、失敗次數及耗時等資訊的摘要。錯誤會連同對應的檔案名稱及失敗原因一併列出。

此流程區分三種結果類別:成功(找到並解碼BarCode)、空(讀取檔案但未偵測到BarCode)以及失敗(拋出例外)。 此區別至關重要,因為空讀取與失敗情況需要不同的處理方式。 讀取失敗可能需要更廣泛的格式設定,而讀取失敗通常表示基礎架構問題,例如檔案遺失、資源被鎖定或缺少原生依賴項。

錯誤清單會保留各檔案的上下文,以支援根本原因分析。 在 CI/CD 管道中,請解析此輸出結果以設定退出代碼(完全成功時為 0,當 failCount 大於 0 時則為非零值),或將錯誤詳細資訊轉發至警示系統。

若需提升處理效能,請將 Multithreaded 設為 true 並調整 MaxParallelThreads 以配合可用 CPU 核心數,以啟用平行處理。 請透過將並行迭代包覆在 Parallel.ForEach 標籤中,並使用線程安全的集合來管理錯誤清單,以維持每檔文件的隔離性。


延伸閱讀

當開發流程準備投入生產環境時,請查看授權選項

常見問題

如何處理使用 IronBarcode 進行 BARCODE 操作時的錯誤?

IronBarcode 提供類型化例外狀況與內建記錄功能,可有效管理並處理 BarCode 操作中的錯誤,確保您的應用程式順暢運行。

IronBarcode 提供哪些用於除錯 BarCode 問題的功能?

IronBarcode 包含診斷性資料擷取及可直接投入生產環境的批次錯誤隔離功能,協助開發人員有效率地識別並解決 BarCode 相關問題。

IronBarcode 能否在 BarCode 處理過程中記錄錯誤?

是的,IronBarcode 具備內建的記錄功能,讓開發人員能在 BarCode 處理過程中擷取並記錄錯誤詳情,從而更輕鬆地進行除錯。

IronBarcode 中的「類型化例外」是什麼?

IronBarcode 中的「類型化例外」是特定類型的錯誤,會提供有關 BarCode 操作問題的詳細資訊,讓開發人員更容易診斷並解決問題。

IronBarcode 如何協助進行批次錯誤隔離?

IronBarcode 提供可直接投入生產的批次錯誤隔離功能,有助於將錯誤的 BarCode 操作與成功的操作區分開來,從而簡化批次處理中的錯誤管理。

是否有方法能透過 IronBarcode 從條碼操作中擷取診斷資訊?

是的,IronBarcode 提供診斷擷取工具,協助開發人員蒐集 BarCode 運作的詳細資訊,以利故障排除與錯誤解決。

IronBarcode是否提供自定義條碼外觀的支持?

是的,IronBarcode提供了廣泛的條碼外觀自定義選項,包括顏色、大小和文字註釋,讓您可以根據具體設計需求定制條碼。

IronBarcode如何幫助改善業務流程效率?

IronBarcode通過使條碼生成和讀取快速且準確來提高業務流程效率,減少手動數據輸入錯誤,並改善庫存和資產追蹤。

將IronBarcode實現於專案中需要什麼程式設計技能?

基本的C#程式設計知識足以將IronBarcode實現於專案中,因為它提供了簡單的方法和全面的文檔來指導開發者。

IronBarcode適合於小型專案和大型企業應用嗎?

IronBarcode設計為可擴展且多功能,使其適合小型專案和需要強大條碼解決方案的大型企業應用。

Curtis Chau
技術撰稿人

Curtis Chau 擁有卡爾頓大學(Carleton University)的電腦科學學士學位,專精於前端開發,並精通 Node.js、TypeScript、JavaScript 及 React。他熱衷於打造直觀且美觀的用戶介面,喜歡運用現代框架,並創建結構完善、視覺上吸引人的手冊。

除了開發工作之外,Curtis 對物聯網(IoT)抱有濃厚興趣,致力於探索整合硬體與軟體的創新方法。閒暇時,他喜歡玩遊戲和開發 Discord 機器人,將對科技的熱愛與創意相結合。

準備好開始了嗎?
Nuget 下載 2,240,258 | 版本: 2026.5 just released
Still Scrolling Icon

還在捲動嗎?

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