如何在C#中处理错误和调试条码操作

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

条形码处理流程可能会悄无声息地失败,结果为零通常会被误认为是"未检测到条形码"。然而,诸如文件损坏、受密码保护的 PDF 文件或格式不匹配等问题都可能是造成这种情况的原因。 实施适当的日志记录和结构化的错误处理可以发现这些故障并提供可操作的诊断信息。

IronBarcode在IronBarCode.Exceptions 命名空间中提供类型化的异常层次结构、内置的日志记录 API 和详细的 BarcodeResult 属性。 这些属性包括检测到的格式、解码值、页码以及每次成功解码的坐标。

本指南解释了如何捕获和解释类型化异常、从失败的读取中提取诊断上下文、启用结构化日志记录以及隔离批量操作期间的故障。

快速入门:处理条码错误并启用诊断

将读/写调用包装在针对IronBarcode类型异常的try-catch块中,以显现可操作的错误信息,而不是静默失败。

  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提供密码,或跳过文件并记录
IronBarCodeEncodingException在生成条码时发生的通用编码故障验证输入数据符合目标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无效的置信度阈值参数传递给读取器选项确保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 对象提供了用于事后分析的有用属性,包括 PageNumberPoints (角坐标)。 如果存在结果但与预期不符,请先将 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 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

准备开始了吗?
Nuget 下载 2,143,620 | 版本: 2026.4 刚刚发布
Still Scrolling Icon

还在滚动吗?

想快速获得证据? PM > Install-Package BarCode
运行示例 观看您的字符串变成 BarCode。