IRONSOFTWAREHOME
使用IRONBARCODE

C# USB條碼掃描器:構建完整的掃描應用程式

Curtis Chau
Curtis Chau
Updated: 2026年6月28日

USB 條碼掃描器作為標準鍵盤輸入裝置連接到 C# 應用程式,將掃描的資料作為輸入字元並附帶迴車按鍵發送。 這種 HID 鍵盤楔模式的行為使整合變得簡單,您的應用程式收到文字輸入而不需要任何特殊的驅動程式或 SDK。 IronBarcode 處理這些原始輸入來驗證格式、提取結構化資料,並生成回應條碼,將簡單的掃描事件轉變為完整的資料管道,用於庫存管理、零售銷售點和物流跟蹤系統。

零售、倉儲和製造運營都依賴於準確且快速的條碼掃描。 當開發者將 USB 掃描器連接到 Windows Forms 或 WPF 應用程式時,掃描器的表現如同鍵盤一樣,資料到達 TextBox,按下 Enter 表示已接收到完整條碼。 挑戰不在於捕捉資料; 而是在於正確地處理它。 IronBarcode 的條碼驗證檢查格式完整性,提取批次號或 GS1 應用識別碼等字段,並可立即生成新條碼作為回應。

本指南逐步說明如何構建可以投入生產的 C# USB 條碼掃描器應用程式。您將安裝程式庫、捕獲掃描器輸入、驗證條碼格式、生成回應標籤,並組裝高容量的基於隊列的處理器。 每個部分包含完整、可運行的程式碼,針對 .NET 10 的頂級語句風格。

USB 條碼掃描器與 C# 如何協同工作?

為什麼 HID 鍵盤楔模式使整合變得簡單?

大多數 USB 條碼掃描器出廠時預設配置為 HID 鍵盤楔模式。 當您將其插入 Windows 機器時,操作系統將其註冊為 USB 儲存裝置(用於配置)和鍵盤(用於資料輸入)。 當掃描條碼時,裝置將解碼後的條碼值轉換為按鍵並發送到當前獲得焦點的應用程式窗口,最後附上回車符。

從 C# 開發者的角度來看,這意味著您不需要供應商 SDK、COM 程式庫或特殊的 USB API。僅需一個帶有 KeyDown 處理程式的標準 TextBox 鍵入即可捕獲輸入。 主要的整合挑戰是區分掃描器輸入和真正的鍵盤鍵入。 掃描器通常在非常短的時間內傳送所有字元——通常不足 50 毫秒——而人類鍵入則將按鍵分散在數百毫秒之間。 時序突發是一種可靠的方式來過濾出意外的按鍵。

專業級掃描器還支持串行(RS-232 或虛擬 COM 埠)和直接 USB HID 模式,這使您能更好地控制前綴/後綴字元和掃描觸發。 以下接口模式可處理這兩種情況:

public interface IScannerInput
{
    event EventHandler<string> BarcodeScanned;
    void StartListening();
    void StopListening();
}

public class KeyboardWedgeScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private readonly TextBox _inputBox;
    private readonly System.Windows.Forms.Timer _burstTimer;
    private readonly System.Text.StringBuilder _buffer = new();

    public KeyboardWedgeScanner(TextBox inputBox)
    {
        _inputBox = inputBox;
        _burstTimer = new System.Windows.Forms.Timer { Interval = 80 };
        _burstTimer.Tick += OnBurstTimeout;
        _inputBox.KeyPress += OnKeyPress;
    }

    private void OnKeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == (char)Keys.Enter)
        {
            _burstTimer.Stop();
            string value = _buffer.ToString().Trim();
            _buffer.Clear();
            if (value.Length > 0)
                BarcodeScanned?.Invoke(this, value);
        }
        else
        {
            _buffer.Append(e.KeyChar);
            _burstTimer.Stop();
            _burstTimer.Start();
        }
        e.Handled = true;
    }

    private void OnBurstTimeout(object sender, EventArgs e)
    {
        _burstTimer.Stop();
        _buffer.Clear(); // incomplete burst -- discard
    }

    public void StartListening() => _inputBox.Focus();
    public void StopListening() => _inputBox.Enabled = false;
}

public class SerialPortScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private readonly System.IO.Ports.SerialPort _port;

    public SerialPortScanner(string portName, int baudRate = 9600)
    {
        _port = new System.IO.Ports.SerialPort(portName, baudRate);
        _port.DataReceived += OnDataReceived;
    }

    private void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string data = _port.ReadLine().Trim();
        if (data.Length > 0)
            BarcodeScanned?.Invoke(this, data);
    }

    public void StartListening() => _port.Open();
    public void StopListening() => _port.Close();
}

鍵盤楔實現中的突發計時器是關鍵細節。 它每次按鍵時都會重設,只有當字元停止到達時才會觸發——這意味著真正的鍵盤使用者若噴射過於緩慢則會被其不完整輸入丟棄而不是被視為條碼掃描。

如何處理多種掃描器品牌?

企業環境中經常在同一層樓運行混合的 Honeywell、Zebra(前身為 Symbol/Motorola)和 Datalogic 掃描器。 每個供應商都有其預設終止符字元、波特率和前後綴約定。 配置模型保持您的應用程式靈活性:

public class ScannerConfiguration
{
    public string ScannerType { get; set; } = "KeyboardWedge";
    public string PortName { get; set; } = "COM3";
    public int BaudRate { get; set; } = 9600;
    public string Terminator { get; set; } = "\r\n";
    public bool EnableBeep { get; set; } = true;
    public Dictionary<string, string> BrandSettings { get; set; } = new();

    public static ScannerConfiguration GetHoneywellConfig() => new()
    {
        ScannerType = "Serial",
        BaudRate = 115200,
        BrandSettings = new Dictionary<string, string>
        {
            { "Prefix", "STX" },
            { "Suffix", "ETX" },
            { "TriggerMode", "Manual" }
        }
    };

    public static ScannerConfiguration GetZebraConfig() => new()
    {
        ScannerType = "KeyboardWedge",
        BrandSettings = new Dictionary<string, string>
        {
            { "ScanMode", "Continuous" },
            { "BeepVolume", "High" }
        }
    };
}

在設置文件或資料庫中儲存這些配置意味著倉庫工作人員可以在不需要重新部署的情況下更換掃描器型號。 ScannerType 字段驅動在啟動時實例化哪個 IScannerInput 實現。

如何在 C# 專案中安裝 IronBarcode?

通過 NuGet 新增 IronBarcode 的最快方式是什麼?

在Visual Studio中打開套件管理器控制臺並運行:

PM > Install-Package BarCode

或者,使用.NET CLI:

dotnet add package BarCode

這兩個命令從 NuGet.org 提取當前發佈版本並將組件引用新增到您的專案文件中。程式庫目標是 .NET Standard 2.0,因此可在 .NET Framework 4.6.2 到 .NET 10 上運行,無需其他相容性填充。

安裝後,在調用任何 IronBarcode 方法之前設置您的授權金鑰。 對於開發和評估,您可以從 IronBarcode 授權頁面獲取免費試用金鑰:

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";

對於容器化部署,IronBarcode 支持在 Linux 上的 Docker,對於雲端功能,支持 AWS LambdaAzure 功能

如何使用 IronBarcode 驗證掃描的條碼?

格式驗證的正確方法是什麼?

IronBarcode supports over 30 barcode symbologies including Code 128, EAN-13, Code 39, QR codes, and Data Matrix. 對於 USB 掃描器應用程式,驗證模塊將掃描的字串重新編碼為條碼圖像,並立即通過解碼器將其讀取回來。 這種往返確認了該字串是聲明格式的有效值:

public class BarcodeValidator
{
    public async Task<ValidationResult> ValidateAsync(string scannedText, BarcodeEncoding preferredFormat = BarcodeEncoding.Code128)
    {
        var result = new ValidationResult { RawInput = scannedText };

        try
        {
            var barcode = BarcodeWriter.CreateBarcode(scannedText, preferredFormat);
            var readResults = await BarcodeReader.ReadAsync(barcode.ToBitmap());

            if (readResults.Any())
            {
                var first = readResults.First();
                result.IsValid = true;
                result.Format = first.BarcodeType;
                result.Value = first.Value;
                result.Confidence = first.Confidence;
            }
            else
            {
                result.IsValid = false;
                result.Error = "No barcode could be decoded from the scanned input.";
            }
        }
        catch (Exception ex)
        {
            result.IsValid = false;
            result.Error = ex.Message;
        }

        return result;
    }
}

public record ValidationResult
{
    public string RawInput { get; init; } = "";
    public bool IsValid { get; set; }
    public BarcodeEncoding Format { get; set; }
    public string Value { get; set; } = "";
    public float Confidence { get; set; }
    public string Error { get; set; } = "";
}

對於供應鏈應用中使用的 GS1-128 條碼,掃描的字串包括在括號中的是應用標識符前綴,例如 (01) 用於 GTIN 和 (17) 用於到期日。 當您指定 BarcodeEncoding.GS1_128 時,IronBarcode 自動解析這些應用標識符。

開發者應實施哪種 EAN-13 校驗碼邏輯?

零售銷售點應用通常需要在將值傳遞給定價查詢之前獨立驗證 EAN-13 校驗位。EAN-13 的 Luhn 風格校驗算法在前 12 位中交替使用權重 1 和 3:

public static bool ValidateEan13Checksum(string value)
{
    if (value.Length != 13 || !value.All(char.IsDigit))
        return false;

    int sum = 0;
    for (int i = 0; i < 12; i++)
    {
        int digit = value[i] - '0';
        sum += (i % 2 == 0) ? digit : digit * 3;
    }

    int expectedCheck = (10 - (sum % 10)) % 10;
    return expectedCheck == (value[12] - '0');
}

此純邏輯檢查在編碼之前運行,以避免在高容量零售環境中每次掃描生成的圖像往返開銷。 根據 GS1 規範,當您刪除開頭的零時,UPCA(12 位)的校驗位算法與 UPC-A 相同。

如何從掃描輸入中生成回應條碼?

應用程式何時在掃描後建立新條碼?

倉庫收貨中的常見模式是"掃描和重新標籤"工作流程:進貨商品帶有供應商條碼(通常是 EAN-13 或 ITF-14),倉庫管理系統需要列印帶有其自身位置和批次程式碼的內部 Code 128 標籤。 IronBarcode 的生成功能可以用幾行程式碼處理這一過程:

public class InventoryLabelGenerator
{
    private readonly string _outputDirectory;

    public InventoryLabelGenerator(string outputDirectory)
    {
        _outputDirectory = outputDirectory;
        Directory.CreateDirectory(_outputDirectory);
    }

    public async Task<string> GenerateLabelAsync(string internalCode, string locationCode)
    {
        string fullCode = $"{internalCode}|{locationCode}|{DateTime.UtcNow:yyyyMMdd}";

        // Primary Code 128 label for scanners
        var linearBarcode = BarcodeWriter.CreateBarcode(fullCode, BarcodeEncoding.Code128);
        linearBarcode.ResizeTo(500, 140);
        linearBarcode.SetMargins(12);
        linearBarcode.AddAnnotationTextAboveBarcode(fullCode);
        linearBarcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black);

        // QR code companion for mobile apps
        var qrCode = BarcodeWriter.CreateQrCode(fullCode);
        qrCode.ResizeTo(200, 200);
        qrCode.SetMargins(8);

        string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
        string pngPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.png");
        string pdfPath = Path.Combine(_outputDirectory, $"{internalCode}_{timestamp}.pdf");

        await Task.Run(() =>
        {
            linearBarcode.SaveAsPng(pngPath);
            linearBarcode.SaveAsPdf(pdfPath);
        });

        return pngPath;
    }
}

保存為 PDF 對於接受 PDF 輸入的網路共享標籤列印機特別有用。 您還可以導出為 SVG以獲得矢量品質的熱感應標籤輸出,或導出為字節流直接發送至標籤列印機 API。

IronBarcode 支持豐富的樣式自定義包括自定義顏色、邊距調整、可讀文字覆蓋,對於 QR code,標誌嵌入用於品牌標示的行動標籤。

Windows Forms 應用程式介面展示 IronBarcode 的雙條碼生成功能。 介面顯示對庫存編號 'INV-20250917-helloworld' 成功生成 Code 128 線性條碼和 QR code。 頂部的輸入區域允許使用者輸入自定義庫存程式碼,並使用"生成"按鈕建立條碼。 成功訊息"項目成功處理 - 已生成標籤"確認操作已完成。 Code 128 條碼標示為主要庫存跟蹤格式,而下面的 QR code 則標示為行動友好的替代方案。該應用程式使用專業的灰色背景和清晰的視覺層次結構,展示了如何使用 IronBarcode 使開發者能夠建立多格式條碼生成系統以管理完整的庫存系統。

如何構建完整的高容量掃描應用程式?

什麼是生產隊列為基礎的實現樣式?

對於每分鐘處理數十次掃描的應用程式,UI 執行緒上的簡單同步處理程式會成為瓶頸。 下面的模式使用 ConcurrentQueue<t> 将掃描捕獲與處理解耦,並設置後台處理迴圈。IronBarcode 的異步 API處理驗證而不會阻礙 UI:

using IronBarCode;
using System.Collections.Concurrent;

public partial class HighVolumeScanner : Form
{
    private readonly ConcurrentQueue<(string Data, DateTime Timestamp)> _scanQueue = new();
    private readonly SemaphoreSlim _semaphore;
    private readonly CancellationTokenSource _cts = new();
    private IScannerInput _scanner;

    public HighVolumeScanner()
    {
        InitializeComponent();
        IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
        _semaphore = new SemaphoreSlim(Environment.ProcessorCount);
        InitializeScanner();
        _ = RunProcessingLoopAsync();
    }

    private void InitializeScanner()
    {
        _scanner = System.IO.Ports.SerialPort.GetPortNames().Any()
            ? new SerialPortScanner("COM3", 115200)
            : new KeyboardWedgeScanner(txtScannerInput);

        _scanner.BarcodeScanned += (_, barcode) =>
            _scanQueue.Enqueue((barcode, DateTime.UtcNow));

        _scanner.StartListening();
    }

    private async Task RunProcessingLoopAsync()
    {
        while (!_cts.Token.IsCancellationRequested)
        {
            if (_scanQueue.TryDequeue(out var scan))
            {
                await _semaphore.WaitAsync(_cts.Token);
                _ = Task.Run(async () =>
                {
                    try { await ProcessScanAsync(scan.Data, scan.Timestamp); }
                    finally { _semaphore.Release(); }
                }, _cts.Token);
            }
            else
            {
                await Task.Delay(10, _cts.Token);
            }
        }
    }

    private async Task ProcessScanAsync(string rawData, DateTime scanTime)
    {
        var options = new BarcodeReaderOptions
        {
            Speed = ReadingSpeed.Balanced,
            ExpectMultipleBarcodes = false,
            ExpectBarcodeTypes = BarcodeEncoding.Code128 | BarcodeEncoding.QRCode,
            MaxParallelThreads = 1
        };

        var testBarcode = BarcodeWriter.CreateBarcode(rawData, BarcodeEncoding.Code128);
        var results = await BarcodeReader.ReadAsync(testBarcode.ToBitmap(), options);

        if (results.Any())
        {
            var item = results.First();
            BeginInvoke(() => UpdateInventoryDisplay(item.Value, scanTime));
        }
        else
        {
            BeginInvoke(() => LogRejectedScan(rawData, scanTime));
        }
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        _cts.Cancel();
        _scanner.StopListening();
        base.OnFormClosing(e);
    }
}

SemaphoreSlim 限制同時運行的驗證任務數量至邏輯處理器數,以防止突發掃描事件期間的失控執行緒建立。 BeginInvoke 調用將 UI 更新安全地編組回主執行緒。

如何為不同的掃描量調整性能?

BarcodeReaderOptions.Speed 屬性接受 ReadingSpeed.平衡ReadingSpeed.詳細。 對於已知字串值的 USB 掃描器輸入,平衡 是合適的選擇——解碼器只需要確認格式,而不是在圖像中尋找條碼。 根據IronBarcode 的讀取速度文件較快 模式跳過了一些變形糾正算法,這對於乾淨的掃描器輸出來說是安全的,但可能會錯過影像場景中的損壞條碼。

下表總結了每種速度模式何時使用:

IronBarcode 讀取速度模式及其適用情況
速度模式最佳適用於權衡
較快乾淨的 USB 掃描器輸入,高容量吞吐量可能漏掉嚴重損壞或傾斜的條碼
平衡混合輸入——USB 掃描器加上圖像匯入中等 CPU 使用,優良的準確性
詳細損壞標籤、低對比印刷、PDF 匯入較高的 CPU 使用,最慢的處理速度

對於同時處理影像或 PDF 與 USB 掃描器輸入的應用程式,IronBarcode 可以從 PDF 文件中讀取條碼,以及多頁 TIFF 檔案使用相同的 API 表面。

階檯專業的 Windows Forms 條碼掃描器應用程式展示 IronBarcode 即時庫存跟蹤功能。 介面設計有整潔的雙面板設計,帶有精緻的深藍色標題。 左側面板顯示掃描歷史列表,顯示四個成功掃描的庫存項目(INV-001 至 INV-004),帶有精確的時間戳和掃描狀態指示。 每個項目包括詳細的市資料如條碼型別和信心水平。 右側面板顯示動態生成的摘要條碼,展示"項目:4"並具有專業樣式和適當邊距。 底部的動作按鈕包括"清除列表"、"導出資料"和"列印標籤"以完成庫存管理。 狀態欄顯示"掃描器:已連接|模式:連續|最後掃描:2秒前",展示應用程式的實時監控功能以及 IronBarcode 對生產庫存系統提供的專業企業級設計。

如何在掃描應用程式中處理邊界情況和錯誤?

開發者應預料那些失效模式?

USB 掃描器應用程式以可預測的方式失效。 最常見的問題及其緩解措施如下:

掃描器斷開——當 USB 掃描器拔出時,鍵盤楔 TextBox 失去了其虛擬鍵盤。 最簡單的緩解措施是負責檢查 _inputBox.Focused 並在掃描器仍在連接的 HID 裝置清單中重新聚焦它。 對於串行掃描器,SerialPort.GetPortNames() 檢測重新連接。

模糊的條碼格式——有些產品攜帶的條碼在多個標誌中有效。 例如,一個12位字串同時是合法的 UPC-A 和 Code 128。在 BarcodeReaderOptions 中指定 ExpectBarcodeTypes 可將解碼器限制到您預期格式,消除歧義。 IronBarcode 故障排解指南涵蓋格式特定的識別技巧。

無效格式的例外狀況——如果 BarcodeWriter.CreateBarcode 收到違反選擇編碼規則的字串(例如,數字專用 EAN-13 字段中的字母字元),它會拋出一個 IronBarCode.Exceptions.InvalidBarcodeException。 將調用包裝在 try-catch 中並退回到字串專用驗證路徑可保持應用程式運行。

按鍵計時衝突——在操作員也在同一 TextBox 中手動鍵入的環境中,前面描述的突發計時方法是主要防禦。 次要防護是最小長度:大多數真實條碼至少有 8 個字元,因此可以將短於該長度的字串視為鍵盤輸入。

Microsoft .NET 文件中關於 System.IO.Ports.SerialPort 的內容在排除串行掃描器連接方面特別是ReadTimeoutWriteTimeout 設置方面非常有用。 在零售中的法規合規性方面,GS1 通用規範為每個應用標識符定義了有效值範圍。

如何擴展應用程式到行動和 Web 平台?

上面顯示的掃描器接口模式——IScannerInputBarcodeScanned 事件——將硬體從處理邏輯中抽象出來。 替換實現允許相同的驗證和生成程式碼在不同平台上運行:

  • .NET MAUI 提供了用於 Android 和 iOS 平板電腦的基於相機的掃描器實現,用作行動接收站
  • Blazor Server 支持基於瀏覽器的掃描,JavaScript 相機存取餵入相同的 BarcodeScanned 事件
  • AndroidiOS 原生實現使行動開發者具有相機掃描功能,後端使用相同的 IronBarcode 解碼器

對於雲原生架構,可將驗證和標籤生成步驟作為由佇列消息觸發的 Azure Functions 來運行,桌面應用程式僅作為掃描器輸入閘道。 當標籤列印邏輯必須集中化以進行合規審核時,這種分離特別有用。

您的下一步是什麼?

using IronBarcode 構建 USB 條碼掃描器應用程式涉及四個具體階段:捕獲帶有突發時間檢測的鍵盤楔輸入,通過 IronBarcode 解碼器驗證掃描值,生成所需格式的回應標籤,並使用併發隊列處理高掃描量。 每個階段都獨立且可以單獨進行測試。

從這裡開始,考慮擴展應用程式以用於多條碼讀取以進行批處理,對圖像基礎輸入進行裁剪區域最佳化,或對舊倉庫裝置進行MSI 條碼支持IronBarcode 文件涵蓋所有支持的格式和高級讀者配置選項。

開始免費試用以獲得開發授權金鑰,並立即開始將 IronBarcode 整合到您的掃描應用程式中。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

...
閱讀更多

相關文章

Key in blue circle

立即免費取得 30 天試用金鑰

Your trial license will be sent to your email address

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
預訂您的免費即時演示
Booking Badge

全球數百萬工程師信賴

Iron Software的客戶標誌
獲取您的無義務諮詢
完成下方表單或發送電子郵件至sales@ironsoftware.com
您的詳細資訊將始終保密。
全球數百萬工程師信賴
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立