Skip to footer content
USING IRONBARCODE

How to Build a USB Barcode Scanner Application in C#?

USB barcode scanners act as keyboard input devices, automatically sending scanned data to C# applications. IronBarcode processes this input to validate formats, extract structured data, and generate new barcodes, creating complete scanning solutions for inventory management systems with minimal deployment complexity.

Retail, warehousing, and inventory management operations depend on efficient barcode scanning. With IronBarcode and its effective validation and generation capabilities, developers can build reliable USB barcode scanner applications that go beyond simple data capture. The library validates barcode data, extracts structured information, and generates new barcodes on the fly.

This guide demonstrates how to integrate USB barcode scanners with IronBarcode in C#. The result is a real-time scanning solution that works with both .NET Framework and .NET applications, helping teams manage inventory and track items efficiently. Whether building point-of-sale systems or enterprise inventory management solutions, IronBarcode's cross-platform compatibility ensures applications run smoothly on Windows, Linux, or macOS.

How Do USB Barcode Scanners Work with IronBarcode?

Why Does Keyboard Wedge Mode Matter for Integration?

Most USB barcode scanners operate in HID keyboard wedge mode, emulating keyboard input for effortless code scanning. When scanning a barcode, the scanner "types" the data followed by an Enter key. IronBarcode improve this raw input by validating formats, extracting structured data, and enabling immediate barcode generation in response to scans.

Understanding different scanner communication modes helps in enterprise applications. Professional scanners support serial communication and direct USB HID modes beyond keyboard wedge mode:

// Example: Handling different scanner input modes
public interface IScannerInput
{
    event EventHandler<string> BarcodeScanned;
    void StartListening();
    void StopListening();
}

// Keyboard wedge implementation
public class KeyboardWedgeScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private readonly TextBox _inputBox;

    public KeyboardWedgeScanner(TextBox inputBox)
    {
        _inputBox = inputBox;
        _inputBox.KeyPress += OnKeyPress;
    }

    private void OnKeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == (char)Keys.Enter)
        {
            BarcodeScanned?.Invoke(this, _inputBox.Text);
            _inputBox.Clear();
        }
    }

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

// Serial port implementation for professional scanners
public class SerialPortScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private 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();
        BarcodeScanned?.Invoke(this, data);
    }

    public void StartListening() => _port.Open();
    public void StopListening() => _port.Close();
}
// Example: Handling different scanner input modes
public interface IScannerInput
{
    event EventHandler<string> BarcodeScanned;
    void StartListening();
    void StopListening();
}

// Keyboard wedge implementation
public class KeyboardWedgeScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private readonly TextBox _inputBox;

    public KeyboardWedgeScanner(TextBox inputBox)
    {
        _inputBox = inputBox;
        _inputBox.KeyPress += OnKeyPress;
    }

    private void OnKeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == (char)Keys.Enter)
        {
            BarcodeScanned?.Invoke(this, _inputBox.Text);
            _inputBox.Clear();
        }
    }

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

// Serial port implementation for professional scanners
public class SerialPortScanner : IScannerInput
{
    public event EventHandler<string> BarcodeScanned;
    private 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();
        BarcodeScanned?.Invoke(this, data);
    }

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

How Can Developers Capture and Validate Scanner Input?

// Capture scanner input and validate with IronBarcode
private async void ProcessScannerInput(string scannedData)
{
    try
    {
        // Validate the scanned data format
        var validationBarcode = BarcodeWriter.CreateBarcode(scannedData, BarcodeEncoding.Code128);
        var results = await BarcodeReader.ReadAsync(validationBarcode.ToBitmap());

        if (results.Any())
        {
            var result = results.First();

            // Extract metadata for enterprise systems
            var scanMetadata = new ScanMetadata
            {
                BarcodeType = result.BarcodeType,
                Value = result.Value,
                Confidence = result.Confidence,
                ScanTimestamp = DateTime.UtcNow,
                ScannerDevice = GetCurrentScannerInfo()
            };

            await ProcessValidBarcode(scanMetadata);
        }
        else
        {
            HandleInvalidScan(scannedData);
        }
    }
    catch (Exception ex)
    {
        LogScanError(ex, scannedData);
    }
}
// Capture scanner input and validate with IronBarcode
private async void ProcessScannerInput(string scannedData)
{
    try
    {
        // Validate the scanned data format
        var validationBarcode = BarcodeWriter.CreateBarcode(scannedData, BarcodeEncoding.Code128);
        var results = await BarcodeReader.ReadAsync(validationBarcode.ToBitmap());

        if (results.Any())
        {
            var result = results.First();

            // Extract metadata for enterprise systems
            var scanMetadata = new ScanMetadata
            {
                BarcodeType = result.BarcodeType,
                Value = result.Value,
                Confidence = result.Confidence,
                ScanTimestamp = DateTime.UtcNow,
                ScannerDevice = GetCurrentScannerInfo()
            };

            await ProcessValidBarcode(scanMetadata);
        }
        else
        {
            HandleInvalidScan(scannedData);
        }
    }
    catch (Exception ex)
    {
        LogScanError(ex, scannedData);
    }
}
$vbLabelText   $csharpLabel

This code captures scanner input through various methods and uses IronBarcode's asynchronous reading capabilities to validate scanned data without blocking the UI thread. The confidence threshold feature ensures only high-quality scans are processed in production environments.

How to Set Up Your Barcode Scanner Project?

What Are the Essential Dependencies and Configurations?

Start by creating a Windows Forms application in Visual Studio for desktop scenarios, or consider Blazor for web-based scanning applications. For mobile inventory solutions, .NET MAUI provides excellent cross-platform support with Android and iOS capabilities. Then install IronBarcode through the NuGet Package Manager Console:

Install-Package BarCode

For containerized deployments, IronBarcode works seamlessly with Docker, providing deployment manifests for enterprise environments.

Quickstart: Create QR Code Image in C#

Creating a QR code generates a visual representation encoding data in scannable squares:

Nuget IconGet started making PDFs with NuGet now:

  1. Install IronBarcode with NuGet Package Manager

    PM > Install-Package BarCode

  2. Copy and run this code snippet.

    using IronBarCode;
    
    // Generate QR code from scanned inventory data
    string inventoryCode = "INV-2025-001";
    var qrCode = BarcodeWriter.CreateQrCode(inventoryCode);
    
    // Apply styling for professional labels
    qrCode.ResizeTo(300, 300);
    qrCode.SetMargins(10);
    qrCode.ChangeQrCodeColor(IronSoftware.Drawing.Color.DarkBlue);
    
    // Add logo for branding
    qrCode.AddLogoToQrCode("company_logo.png", 60, 60);
    
    // Save as high-quality image
    qrCode.SaveAsPng("inventory_qr.png");
    
    // Alternative: Save as PDF for printing
    qrCode.SaveAsPdf("inventory_qr.pdf");
  3. Deploy to test on your live environment

    Start using IronBarcode in your project today with a free trial
    arrow pointer

Which Namespaces Should Applications Include?

Add these essential namespaces to forms, along with examples from the documentation:

using IronBarCode;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.IO.Ports; // For serial scanners
using System.Diagnostics; // For performance monitoring
using IronBarCode;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.IO.Ports; // For serial scanners
using System.Diagnostics; // For performance monitoring
$vbLabelText   $csharpLabel

How Should Developers Configure the Scanner Input Form?

Enterprise applications benefit from flexible scanner configuration systems supporting multiple scanner brands:

public class ScannerConfiguration
{
    public string ScannerType { get; set; } // "KeyboardWedge", "Serial", "USB-HID"
    public string PortName { get; set; } // For serial scanners
    public int BaudRate { get; set; } = 9600;
    public string Terminator { get; set; } = "\r\n";
    public bool EnableBeep { get; set; } = true;

    // Brand-specific settings
    public Dictionary<string, string> BrandSettings { get; set; } = new();

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

    public static ScannerConfiguration GetSymbolConfig()
    {
        return new ScannerConfiguration
        {
            ScannerType = "KeyboardWedge",
            BrandSettings = new Dictionary<string, string>
            {
                {"ScanMode", "Continuous"},
                {"BeepVolume", "High"}
            }
        };
    }
}
public class ScannerConfiguration
{
    public string ScannerType { get; set; } // "KeyboardWedge", "Serial", "USB-HID"
    public string PortName { get; set; } // For serial scanners
    public int BaudRate { get; set; } = 9600;
    public string Terminator { get; set; } = "\r\n";
    public bool EnableBeep { get; set; } = true;

    // Brand-specific settings
    public Dictionary<string, string> BrandSettings { get; set; } = new();

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

    public static ScannerConfiguration GetSymbolConfig()
    {
        return new ScannerConfiguration
        {
            ScannerType = "KeyboardWedge",
            BrandSettings = new Dictionary<string, string>
            {
                {"ScanMode", "Continuous"},
                {"BeepVolume", "High"}
            }
        };
    }
}
$vbLabelText   $csharpLabel

How to Validate Scanned Barcodes with IronBarcode?

What's the Best Approach for Barcode Verification?

IronBarcode excels at validating and parsing barcode data across numerous formats. The library supports 1D barcodes like Code 128, EAN-13, and Code 39, plus 2D formats including QR codes and Data Matrix. Here's an improve validation approach:

public class BarcodeValidator
{
    private readonly Dictionary<BarcodeType, Func<string, bool>> _validators;

    public BarcodeValidator()
    {
        _validators = new Dictionary<BarcodeType, Func<string, bool>>
        {
            { BarcodeType.Code128, ValidateCode128 },
            { BarcodeType.EAN13, ValidateEAN13 },
            { BarcodeType.UPCA, ValidateUPCA },
            { BarcodeType.QRCode, ValidateQRCode }
        };
    }

    public async Task<ValidationResult> ValidateScannedBarcodeAsync(string scannedText)
    {
        var result = new ValidationResult();

        try
        {
            // Attempt multiple barcode formats for flexibility
            var encodings = new[] { 
                BarcodeEncoding.Code128, 
                BarcodeEncoding.EAN13,
                BarcodeEncoding.UPCA,
                BarcodeEncoding.QRCode 
            };

            foreach (var encoding in encodings)
            {
                try
                {
                    var barcode = BarcodeWriter.CreateBarcode(scannedText, encoding);
                    var validationResults = await BarcodeReader.ReadAsync(barcode.ToBitmap());

                    if (validationResults.Any())
                    {
                        var validated = validationResults.First();
                        result.IsValid = true;
                        result.Format = validated.BarcodeType;
                        result.Value = validated.Value;
                        result.Confidence = validated.Confidence;

                        // Apply format-specific validation
                        if (_validators.ContainsKey(validated.BarcodeType))
                        {
                            result.PassesBusinessRules = _validators___PROTECTED_LINK_35___;
                        }

                        break;
                    }
                }
                catch { /* Try next format */ }
            }

            // Handle GS1-128 for supply chain applications
            if (!result.IsValid && IsGS1Format(scannedText))
            {
                result = await ValidateGS1BarcodeAsync(scannedText);
            }
        }
        catch (Exception ex)
        {
            result.Error = ex.Message;
        }

        return result;
    }

    private bool ValidateEAN13(string value)
    {
        // EAN-13 checksum validation
        if (value.Length != 13) return false;

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

        int checkDigit = (10 - (sum % 10)) % 10;
        return checkDigit == int.Parse(value[12].ToString());
    }
}
public class BarcodeValidator
{
    private readonly Dictionary<BarcodeType, Func<string, bool>> _validators;

    public BarcodeValidator()
    {
        _validators = new Dictionary<BarcodeType, Func<string, bool>>
        {
            { BarcodeType.Code128, ValidateCode128 },
            { BarcodeType.EAN13, ValidateEAN13 },
            { BarcodeType.UPCA, ValidateUPCA },
            { BarcodeType.QRCode, ValidateQRCode }
        };
    }

    public async Task<ValidationResult> ValidateScannedBarcodeAsync(string scannedText)
    {
        var result = new ValidationResult();

        try
        {
            // Attempt multiple barcode formats for flexibility
            var encodings = new[] { 
                BarcodeEncoding.Code128, 
                BarcodeEncoding.EAN13,
                BarcodeEncoding.UPCA,
                BarcodeEncoding.QRCode 
            };

            foreach (var encoding in encodings)
            {
                try
                {
                    var barcode = BarcodeWriter.CreateBarcode(scannedText, encoding);
                    var validationResults = await BarcodeReader.ReadAsync(barcode.ToBitmap());

                    if (validationResults.Any())
                    {
                        var validated = validationResults.First();
                        result.IsValid = true;
                        result.Format = validated.BarcodeType;
                        result.Value = validated.Value;
                        result.Confidence = validated.Confidence;

                        // Apply format-specific validation
                        if (_validators.ContainsKey(validated.BarcodeType))
                        {
                            result.PassesBusinessRules = _validators___PROTECTED_LINK_35___;
                        }

                        break;
                    }
                }
                catch { /* Try next format */ }
            }

            // Handle GS1-128 for supply chain applications
            if (!result.IsValid && IsGS1Format(scannedText))
            {
                result = await ValidateGS1BarcodeAsync(scannedText);
            }
        }
        catch (Exception ex)
        {
            result.Error = ex.Message;
        }

        return result;
    }

    private bool ValidateEAN13(string value)
    {
        // EAN-13 checksum validation
        if (value.Length != 13) return false;

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

        int checkDigit = (10 - (sum % 10)) % 10;
        return checkDigit == int.Parse(value[12].ToString());
    }
}
$vbLabelText   $csharpLabel

For multi-page documents, IronBarcode can read barcodes from PDFs and multipage TIFF files.

Which Barcode Formats Can Applications Validate?

This validation method supports all major 1D barcode formats and 2D barcode formats. For specialized applications, IronBarcode also supports MSI barcodes and GS1-128 formats commonly used in supply chain management.

How to Generate Response Barcodes from Scanned Input?

When Should Applications Create New Barcodes from Scan Data?

Transform scanned data into new barcodes for labeling, tracking, or inventory management with production-ready features. IronBarcode's generation capabilities support creating barcodes from various data types. Export barcodes as images, PDFs, HTML, or streams:

public class InventoryBarcodeGenerator
{
    private readonly string _labelPath = "labels";

    public InventoryBarcodeGenerator()
    {
        // Ensure proper licensing for production use
        IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
        System.IO.Directory.CreateDirectory(_labelPath);
    }

    public async Task<GeneratedBarcode> GenerateInventoryLabelAsync(string productCode, InventoryAction action)
    {
        try
        {
            // Generate structured inventory code
            var inventoryCode = GenerateStructuredCode(productCode, action);

            // Create high-quality barcode with production settings
            var barcode = BarcodeWriter.CreateBarcode(inventoryCode, BarcodeEncoding.Code128);

            // Apply enterprise styling
            barcode.ResizeTo(400, 120);
            barcode.SetMargins(10);
            barcode.AddAnnotationTextAboveBarcode(inventoryCode, IronSoftware.Drawing.Font.Arial, 12);
            barcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black);

            // Add data matrix for redundancy in warehouse environments
            var dataMatrix = BarcodeWriter.CreateBarcode(inventoryCode, BarcodeEncoding.DataMatrix);
            dataMatrix.ResizeTo(100, 100);

            // Save with error handling
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            var fileName = $"{inventoryCode}_{timestamp}";

            // Save as multiple formats for flexibility
            await Task.Run(() =>
            {
                barcode.SaveAsPng($"{_labelPath}\\{fileName}.png");
                barcode.SaveAsPdf($"{_labelPath}\\{fileName}.pdf");
                barcode.SaveAsSvg($"{_labelPath}\\{fileName}.svg");
            });

            return new GeneratedBarcode
            {
                Code = inventoryCode,
                LinearBarcodePath = $"{_labelPath}\\{fileName}.png",
                DataMatrixPath = $"{_labelPath}\\{fileName}_dm.png",
                Timestamp = DateTime.UtcNow
            };
        }
        catch (Exception ex)
        {
            throw new BarcodeGenerationException($"Failed to generate barcode for {productCode}", ex);
        }
    }

    private string GenerateStructuredCode(string productCode, InventoryAction action)
    {
        // Implement GS1 Application Identifiers for enterprise compatibility
        var ai = action switch
        {
            InventoryAction.Receive => "10", // Batch/Lot number
            InventoryAction.Ship => "400", // Customer purchase order
            InventoryAction.Count => "37", // Quantity
            _ => "91" // Internal use
        };

        return $"({ai}){DateTime.Now:yyMMdd}{productCode}";
    }
}
public class InventoryBarcodeGenerator
{
    private readonly string _labelPath = "labels";

    public InventoryBarcodeGenerator()
    {
        // Ensure proper licensing for production use
        IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
        System.IO.Directory.CreateDirectory(_labelPath);
    }

    public async Task<GeneratedBarcode> GenerateInventoryLabelAsync(string productCode, InventoryAction action)
    {
        try
        {
            // Generate structured inventory code
            var inventoryCode = GenerateStructuredCode(productCode, action);

            // Create high-quality barcode with production settings
            var barcode = BarcodeWriter.CreateBarcode(inventoryCode, BarcodeEncoding.Code128);

            // Apply enterprise styling
            barcode.ResizeTo(400, 120);
            barcode.SetMargins(10);
            barcode.AddAnnotationTextAboveBarcode(inventoryCode, IronSoftware.Drawing.Font.Arial, 12);
            barcode.ChangeBarCodeColor(IronSoftware.Drawing.Color.Black);

            // Add data matrix for redundancy in warehouse environments
            var dataMatrix = BarcodeWriter.CreateBarcode(inventoryCode, BarcodeEncoding.DataMatrix);
            dataMatrix.ResizeTo(100, 100);

            // Save with error handling
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            var fileName = $"{inventoryCode}_{timestamp}";

            // Save as multiple formats for flexibility
            await Task.Run(() =>
            {
                barcode.SaveAsPng($"{_labelPath}\\{fileName}.png");
                barcode.SaveAsPdf($"{_labelPath}\\{fileName}.pdf");
                barcode.SaveAsSvg($"{_labelPath}\\{fileName}.svg");
            });

            return new GeneratedBarcode
            {
                Code = inventoryCode,
                LinearBarcodePath = $"{_labelPath}\\{fileName}.png",
                DataMatrixPath = $"{_labelPath}\\{fileName}_dm.png",
                Timestamp = DateTime.UtcNow
            };
        }
        catch (Exception ex)
        {
            throw new BarcodeGenerationException($"Failed to generate barcode for {productCode}", ex);
        }
    }

    private string GenerateStructuredCode(string productCode, InventoryAction action)
    {
        // Implement GS1 Application Identifiers for enterprise compatibility
        var ai = action switch
        {
            InventoryAction.Receive => "10", // Batch/Lot number
            InventoryAction.Ship => "400", // Customer purchase order
            InventoryAction.Count => "37", // Quantity
            _ => "91" // Internal use
        };

        return $"({ai}){DateTime.Now:yyMMdd}{productCode}";
    }
}
$vbLabelText   $csharpLabel

For specialized requirements, developers can create 1-BPP barcode images for high-contrast printing or stamp barcodes on existing PDFs.

What Customization Options Are Available for Generated Barcodes?

IronBarcode provides extensive customization options including color changes, margin settings, and QR code styling with logo embedding.

Windows Forms application interface demonstrating IronBarcode's dual barcode generation capabilities. The interface shows successful generation of both a Code 128 linear barcode and QR code for inventory number 'INV-20250917-helloworld'. The input field at the top allows users to enter custom inventory codes, with a 'Generate' button to create the barcodes. The success message 'Item processed successfully - Generated Labels' confirms the operation completed. The Code 128 barcode is labeled as the primary inventory tracking format, while the QR code below is marked as a mobile-friendly alternative. The application uses a professional gray background with clear visual hierarchy, demonstrating how IronBarcode enables developers to create multi-format barcode generation systems for complete inventory management.

How to Build a Complete Barcode Scanning Application?

What Does a Production-Ready Scanner Implementation Look Like?

Here's an enterprise-grade implementation with complete error handling and performance optimization. This approach use IronBarcode's performance features and async capabilities for improve throughput:

using IronBarCode;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EnterpriseBarcodeScanner
{
    public partial class HighVolumeScanner : Form
    {
        private readonly ConcurrentQueue<ScanData> _scanQueue = new();
        private readonly SemaphoreSlim _processingSemaphore;
        private readonly CancellationTokenSource _cancellationTokenSource = new();
        private IScannerInput _activeScanner;
        private int _maxConcurrentProcessing = Environment.ProcessorCount;

        public HighVolumeScanner()
        {
            InitializeComponent();
            _processingSemaphore = new SemaphoreSlim(_maxConcurrentProcessing);
            InitializeScanner();
            StartProcessingQueue();
        }

        private void InitializeScanner()
        {
            // Auto-detect scanner type
            if (SerialPort.GetPortNames().Any(p => p.Contains("COM")))
            {
                _activeScanner = new SerialPortScanner("COM3", 115200);
            }
            else
            {
                _activeScanner = new KeyboardWedgeScanner(txtScanner);
            }

            _activeScanner.BarcodeScanned += OnBarcodeScanned;
            _activeScanner.StartListening();
        }

        private void OnBarcodeScanned(object sender, string barcode)
        {
            // Queue for async processing to maintain scanner responsiveness
            _scanQueue.Enqueue(new ScanData 
            { 
                RawData = barcode, 
                ScanTime = DateTime.UtcNow 
            });
        }

        private async void StartProcessingQueue()
        {
            while (!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                if (_scanQueue.TryDequeue(out var scanData))
                {
                    await _processingSemaphore.WaitAsync();

                    _ = Task.Run(async () =>
                    {
                        try
                        {
                            await ProcessScanAsync(scanData);
                        }
                        finally
                        {
                            _processingSemaphore.Release();
                        }
                    }, _cancellationTokenSource.Token);
                }
                else
                {
                    await Task.Delay(10); // Prevent CPU spinning
                }
            }
        }

        private async Task ProcessScanAsync(ScanData scanData)
        {
            try
            {
                // Validate with timeout for performance
                using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
                var validationTask = ValidateAndProcessBarcodeAsync(scanData.RawData);
                var completedTask = await Task.WhenAny(validationTask, Task.Delay(Timeout.Infinite, cts.Token));

                if (completedTask == validationTask)
                {
                    var result = await validationTask;

                    if (result.Success)
                    {
                        // Update UI thread-safe
                        BeginInvoke(new Action(() =>
                        {
                            AddToInventory(result);
                            GenerateLabelsIfNeeded(result);
                        }));
                    }
                    else
                    {
                        LogScanError(scanData, result.Error);
                    }
                }
                else
                {
                    LogScanTimeout(scanData);
                }
            }
            catch (Exception ex)
            {
                LogCriticalError(ex, scanData);
            }
        }

        private async Task<ProcessingResult> ValidateAndProcessBarcodeAsync(string rawData)
        {
            // Implement smart caching for repeated scans
            if (BarcodeCache.TryGetCached(rawData, out var cachedResult))
            {
                return cachedResult;
            }

            // Use IronBarcode with optimized settings
            var barcodeOptions = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectMultipleBarcodes = false,
                ExpectBarcodeTypes = BarcodeEncoding.Code128 | BarcodeEncoding.QRCode,
                MaxParallelThreads = 1 // Single barcode, no need for parallel
            };

            // Generate and validate
            var testBarcode = BarcodeWriter.CreateBarcode(rawData, BarcodeEncoding.Code128);
            var results = await BarcodeReader.ReadAsync(testBarcode.ToBitmap(), barcodeOptions);

            var result = new ProcessingResult
            {
                Success = results.Any(),
                BarcodeData = results.FirstOrDefault(),
                ProcessingTime = DateTime.UtcNow
            };

            BarcodeCache.Add(rawData, result);
            return result;
        }
    }
}
using IronBarCode;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EnterpriseBarcodeScanner
{
    public partial class HighVolumeScanner : Form
    {
        private readonly ConcurrentQueue<ScanData> _scanQueue = new();
        private readonly SemaphoreSlim _processingSemaphore;
        private readonly CancellationTokenSource _cancellationTokenSource = new();
        private IScannerInput _activeScanner;
        private int _maxConcurrentProcessing = Environment.ProcessorCount;

        public HighVolumeScanner()
        {
            InitializeComponent();
            _processingSemaphore = new SemaphoreSlim(_maxConcurrentProcessing);
            InitializeScanner();
            StartProcessingQueue();
        }

        private void InitializeScanner()
        {
            // Auto-detect scanner type
            if (SerialPort.GetPortNames().Any(p => p.Contains("COM")))
            {
                _activeScanner = new SerialPortScanner("COM3", 115200);
            }
            else
            {
                _activeScanner = new KeyboardWedgeScanner(txtScanner);
            }

            _activeScanner.BarcodeScanned += OnBarcodeScanned;
            _activeScanner.StartListening();
        }

        private void OnBarcodeScanned(object sender, string barcode)
        {
            // Queue for async processing to maintain scanner responsiveness
            _scanQueue.Enqueue(new ScanData 
            { 
                RawData = barcode, 
                ScanTime = DateTime.UtcNow 
            });
        }

        private async void StartProcessingQueue()
        {
            while (!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                if (_scanQueue.TryDequeue(out var scanData))
                {
                    await _processingSemaphore.WaitAsync();

                    _ = Task.Run(async () =>
                    {
                        try
                        {
                            await ProcessScanAsync(scanData);
                        }
                        finally
                        {
                            _processingSemaphore.Release();
                        }
                    }, _cancellationTokenSource.Token);
                }
                else
                {
                    await Task.Delay(10); // Prevent CPU spinning
                }
            }
        }

        private async Task ProcessScanAsync(ScanData scanData)
        {
            try
            {
                // Validate with timeout for performance
                using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
                var validationTask = ValidateAndProcessBarcodeAsync(scanData.RawData);
                var completedTask = await Task.WhenAny(validationTask, Task.Delay(Timeout.Infinite, cts.Token));

                if (completedTask == validationTask)
                {
                    var result = await validationTask;

                    if (result.Success)
                    {
                        // Update UI thread-safe
                        BeginInvoke(new Action(() =>
                        {
                            AddToInventory(result);
                            GenerateLabelsIfNeeded(result);
                        }));
                    }
                    else
                    {
                        LogScanError(scanData, result.Error);
                    }
                }
                else
                {
                    LogScanTimeout(scanData);
                }
            }
            catch (Exception ex)
            {
                LogCriticalError(ex, scanData);
            }
        }

        private async Task<ProcessingResult> ValidateAndProcessBarcodeAsync(string rawData)
        {
            // Implement smart caching for repeated scans
            if (BarcodeCache.TryGetCached(rawData, out var cachedResult))
            {
                return cachedResult;
            }

            // Use IronBarcode with optimized settings
            var barcodeOptions = new BarcodeReaderOptions
            {
                Speed = ReadingSpeed.Balanced,
                ExpectMultipleBarcodes = false,
                ExpectBarcodeTypes = BarcodeEncoding.Code128 | BarcodeEncoding.QRCode,
                MaxParallelThreads = 1 // Single barcode, no need for parallel
            };

            // Generate and validate
            var testBarcode = BarcodeWriter.CreateBarcode(rawData, BarcodeEncoding.Code128);
            var results = await BarcodeReader.ReadAsync(testBarcode.ToBitmap(), barcodeOptions);

            var result = new ProcessingResult
            {
                Success = results.Any(),
                BarcodeData = results.FirstOrDefault(),
                ProcessingTime = DateTime.UtcNow
            };

            BarcodeCache.Add(rawData, result);
            return result;
        }
    }
}
$vbLabelText   $csharpLabel

For improve performance, implement crop regions to focus scanning on specific image areas. The barcode reader settings allow fine-tuning for different document types.

How Can Teams Implement Fallback Mechanisms?

This enterprise-ready scanner application implements several critical patterns:

  1. Asynchronous Queue Processing: Prevents UI blocking using async operations
  2. Concurrent Processing: Use multiple threads for parallel validation
  3. Smart Caching: Reduces redundant processing for frequent items
  4. Performance Monitoring: Tracks scan rates using reading speed options
  5. Flexible Scanner Support: Auto-detects available hardware
  • Invalid Format: Catch exceptions when BarcodeWriter encounters unsupported data
  • Scanner Disconnection: Implement TextBox focus management to handle scanner removal
  • Data Validation: Use IronBarcode's format-specific encodings to ensure data compatibility
  • Generation Failures: Wrap barcode generation in try-catch blocks
  • Timeout Handling: Consider implementing keystroke timing to differentiate scanner from keyboard input

Professional Windows Forms barcode scanner application showcasing IronBarcode's real-time inventory tracking capabilities. The interface features a clean two-panel design with a sophisticated dark blue header. The left panel displays a scanning history list showing four successfully scanned inventory items (INV-001 through INV-004) with precise timestamps and scan status indicators. Each item includes detailed metadata like barcode type and confidence level. The right panel shows a dynamically generated summary barcode displaying 'Items: 4' with professional styling and proper margins. Action buttons at the bottom include 'Clear List', 'Export Data', and 'Print Labels' for complete inventory management. The status bar indicates 'Scanner: Connected | Mode: Continuous | Last Scan: 2 seconds ago', demonstrating the application's real-time monitoring capabilities and professional enterprise-ready design that IronBarcode enables for production inventory systems.

What Are the Next Steps for Barcode Scanner Projects?

IronBarcode transforms simple USB barcode scanning into intelligent data processing applications. By combining hardware scanner input with IronBarcode's validation, generation, and format conversion capabilities, developers can build reliable scanning solutions for any industry. The library's support for async operations and multithreading ensures applications scale with growing business needs.

For cloud deployments, IronBarcode offers excellent support for AWS Lambda and Azure Functions, enabling serverless barcode processing at scale. The library integrates seamlessly with Docker containers for microservices architectures.

When implementing enterprise inventory systems, consider these architectural patterns:

  1. Microservices: Deploy scanning as separate service using IronBarcode on Docker
  2. Mobile Integration: Extend to devices with Android and iOS support
  3. Web Applications: Build browser-based scanning with Blazor integration
  4. High Availability: Implement redundancy with multiple reading options

Start a free trial to implement professional barcode scanning in C# applications today. For related functionality, explore IronOCR for text recognition capabilities that complement barcode scanning workflows.

Frequently Asked Questions

What is IronBarcode and how does it relate to USB barcode scanners?

IronBarcode is a library that enables developers to build robust C# applications for USB barcode scanning. It offers features like barcode validation, data extraction, and barcode generation.

Can IronBarcode validate barcode data from a USB scanner?

Yes, IronBarcode can validate barcode data captured from a USB scanner, ensuring data integrity and accuracy in your C# applications.

How does IronBarcode handle barcode generation?

IronBarcode can generate new barcodes on the fly, allowing developers to create and print barcodes easily within their C# applications.

Is there error handling support in IronBarcode for USB barcode scanning?

Yes, IronBarcode includes comprehensive error handling to manage common issues that may arise during USB barcode scanning and processing.

What types of barcodes can be scanned using IronBarcode?

IronBarcode supports scanning a wide range of barcode symbologies, including QR codes, UPC, Code 39, and more, making it versatile for various applications.

Can IronBarcode extract structured information from scanned barcodes?

Yes, IronBarcode can extract structured information from scanned barcodes, aiding in efficient data processing and management.

How can I get started with building a USB barcode scanner application in C#?

To start building a USB barcode scanner application in C#, you can utilize IronBarcode along with the provided code examples and documentation to guide your development process.

Jordi Bardia
Software Engineer
Jordi is most proficient in Python, C# and C++, when he isn’t leveraging his skills at Iron Software; he’s game programming. Sharing responsibilities for product testing, product development and research, Jordi adds immense value to continual product improvement. The varied experience keeps him challenged and engaged, and he ...
Read More