Altbilgi içeriğine atla
IRONBARCODE KULLANARAK

C# USB Barkod Tarayıcı: Tam Bir Tarama Uygulaması Oluşturun

USB barkod tarayıcılar, C# uygulamalarına standart klavye giriş aygıtları olarak bağlanır ve taranan verileri bir Enter tuş vuruşunun ardından yazılmış karakterler olarak gönderir. Bu HID klavye kama davranışı, entegrasyonu basit hale getirir -- uygulamanızın metin girişi alması için özel bir sürücü veya SDK gerekmez. IronBarcode, bu ham girdiyi formatları doğrulamak, yapılandırılmış verileri çıkarmak ve yanıt barkodları oluşturmak için işler ve basit bir tarama olayını envanter yönetimi, perakende satış noktası ve lojistik takip sistemleri için eksiksiz bir veri hattına dönüştürür.

Perakende, depolama ve üretim operasyonlarının tümü, doğru ve hızlı barkod taramaya dayanır. Bir geliştirici, bir USB tarayıcıyı bir Windows Forms veya WPF uygulamasına bağladığında, tarayıcı klavye ile aynı şekilde davranır -- veriler bir TextBox'a gelir ve Enter tuşuna basıldığında tam bir barkod alındığını bildirir. Mesele veriyi yakalamakta değildir; doğru işlemede yatmaktadır. IronBarcode'un barkod doğrulaması biçim bütünlüğünü kontrol eder, parti numaraları veya GS1 uygulama tanımlayıcıları gibi alanları çıkarır ve bir yanıt olarak hemen yeni bir barkod oluşturabilir.

Bu kılavuz, üretime hazır bir C# USB barkod tarayıcı uygulamasını adım adım oluşturmaya yönlendirir. Kütüphaneyi yükleyeceksiniz, tarayıcı girdisini yakalayacaksınız, barkod formatlarını doğrulayacaksınız, yanıt etiketleri oluşturacaksınız ve yüksek hacimli bir kuytu tabanlı işlemci toplayacaksınız. Her bölüm, uygun olduğunda üst düzey ifadelerle .NET 10'u hedefleyen eksiksiz ve çalıştırılabilir kod içerir.

USB Barkod Tarayıcılar C# İle Nasıl Çalışır?

HID Klavye Kama Modu Entegrasyonu Neden Basitleştirir?

Çoğu USB barkod tarayıcı, varsayılan olarak HID klavye kama modunda yapılandırılarak gelir. Bir tanesini bir Windows makinesine taktığınızda, işletim sistemi bunu hem bir USB depolama aygıtı (konfigürasyon için) hem de bir klavye (veri girişi için) olarak kaydeder. Bir barkod tarandığında, cihaz, çözümlenmiş barkod değerini tuş vuruşlarına çevirir ve odaklı herhangi bir uygulama penceresine gönderir, sonunda bir taşıma dönüşü ekleyerek.

C# geliştiricisi açısından, bu, satıcı SDK'larına, COM kütüphanelerine veya özel USB API'lerine ihtiyaç duyulmadığı anlamına gelir. Girdiyi yakalamak için bir KeyDown işleyicisi olan standart bir TextBox yeterlidir. Ana entegrasyon zorluğu, tarayıcı girdisini gerçek klavye yazımından ayırt etmektir. Tarayıcılar genellikle tüm karakterleri çok kısa bir patlama süresinde iletir - genellikle 50 milisaniyenin altında - oysa insan yazımı tuş vuruşlarını yüzlerce milisaniye boyunca yayar. Bu patlamanın zamanlaması, yanlışlıkla yapılan tuş vuruşlarını filtrelemek için güvenilir bir yoldur.

Profesyonel dereceli tarayıcılar ayrıca seri (RS-232 veya sanal COM port) ve doğrudan USB HID modlarını destekler, bu da ön ek/son ek karakterleri ve tarama tetikleyicileri üzerinde daha fazla kontrol sağlar. Aşağıdaki arayüz deseni her iki durumu da ele alır:

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();
}
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();
}
Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.IO.Ports

Public Interface IScannerInput
    Event BarcodeScanned As EventHandler(Of String)
    Sub StartListening()
    Sub StopListening()
End Interface

Public Class KeyboardWedgeScanner
    Implements IScannerInput

    Public Event BarcodeScanned As EventHandler(Of String) Implements IScannerInput.BarcodeScanned
    Private ReadOnly _inputBox As TextBox
    Private ReadOnly _burstTimer As Timer
    Private ReadOnly _buffer As New StringBuilder()

    Public Sub New(inputBox As TextBox)
        _inputBox = inputBox
        _burstTimer = New Timer With {.Interval = 80}
        AddHandler _burstTimer.Tick, AddressOf OnBurstTimeout
        AddHandler _inputBox.KeyPress, AddressOf OnKeyPress
    End Sub

    Private Sub OnKeyPress(sender As Object, e As KeyPressEventArgs)
        If e.KeyChar = ChrW(Keys.Enter) Then
            _burstTimer.Stop()
            Dim value As String = _buffer.ToString().Trim()
            _buffer.Clear()
            If value.Length > 0 Then
                RaiseEvent BarcodeScanned(Me, value)
            End If
        Else
            _buffer.Append(e.KeyChar)
            _burstTimer.Stop()
            _burstTimer.Start()
        End If
        e.Handled = True
    End Sub

    Private Sub OnBurstTimeout(sender As Object, e As EventArgs)
        _burstTimer.Stop()
        _buffer.Clear() ' incomplete burst -- discard
    End Sub

    Public Sub StartListening() Implements IScannerInput.StartListening
        _inputBox.Focus()
    End Sub

    Public Sub StopListening() Implements IScannerInput.StopListening
        _inputBox.Enabled = False
    End Sub
End Class

Public Class SerialPortScanner
    Implements IScannerInput

    Public Event BarcodeScanned As EventHandler(Of String) Implements IScannerInput.BarcodeScanned
    Private ReadOnly _port As SerialPort

    Public Sub New(portName As String, Optional baudRate As Integer = 9600)
        _port = New SerialPort(portName, baudRate)
        AddHandler _port.DataReceived, AddressOf OnDataReceived
    End Sub

    Private Sub OnDataReceived(sender As Object, e As SerialDataReceivedEventArgs)
        Dim data As String = _port.ReadLine().Trim()
        If data.Length > 0 Then
            RaiseEvent BarcodeScanned(Me, data)
        End If
    End Sub

    Public Sub StartListening() Implements IScannerInput.StartListening
        _port.Open()
    End Sub

    Public Sub StopListening() Implements IScannerInput.StopListening
        _port.Close()
    End Sub
End Class
$vbLabelText   $csharpLabel

Klavyedeki kama uygulamasının patlama zamanlayıcısı kritik bir detaydır. Her tuş vuruşunda sıfırlanır ve karakterler gelmeyi durdurursa tetiklenir - yani yavaşça yazan gerçek klavye kullanıcılarının eksik girdileri, bir barkod taraması gibi muamele edileceğine atılmış olur.

Birden Fazla Tarayıcı Markasını Nasıl Ele Alırsınız?

Kurumsal ortamlar, genellikle aynı katta Honeywell, Zebra (eski isimleriyle Symbol/Motorola) ve Datalogic tarayıcıları çalıştırır. Her satıcının kendi varsayılan terminal karakteri, baud oranı ve ön ek/son ek gelenekleri vardır. Bir konfigürasyon modeli uygulamanızı esnek tutar:

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" }
        }
    };
}
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" }
        }
    };
}
Option Strict On



Public Class ScannerConfiguration
    Public Property ScannerType As String = "KeyboardWedge"
    Public Property PortName As String = "COM3"
    Public Property BaudRate As Integer = 9600
    Public Property Terminator As String = vbCrLf
    Public Property EnableBeep As Boolean = True
    Public Property BrandSettings As Dictionary(Of String, String) = New Dictionary(Of String, String)()

    Public Shared Function GetHoneywellConfig() As ScannerConfiguration
        Return New ScannerConfiguration() With {
            .ScannerType = "Serial",
            .BaudRate = 115200,
            .BrandSettings = New Dictionary(Of String, String) From {
                {"Prefix", "STX"},
                {"Suffix", "ETX"},
                {"TriggerMode", "Manual"}
            }
        }
    End Function

    Public Shared Function GetZebraConfig() As ScannerConfiguration
        Return New ScannerConfiguration() With {
            .ScannerType = "KeyboardWedge",
            .BrandSettings = New Dictionary(Of String, String) From {
                {"ScanMode", "Continuous"},
                {"BeepVolume", "High"}
            }
        }
    End Function
End Class
$vbLabelText   $csharpLabel

Bu konfigürasyonları bir ayarlar dosyasında veya veritabanında depolamak, depo çalışanlarının tarayıcı modellerini yeniden dağıtım gerektirmeden değiştirmelerini sağlar. ScannerType alanı, başlangıçta hangi IScannerInput uygulamasının oluşturulacağını belirler.

IronBarcode Nasıl Yüklenir Bir C# Projesine?

IronBarcode'u NuGet ile Eklemek İçin En Hızlı Yol Nedir?

Visual Studio'da Paket Yöneticisi Konsolunu açın ve şu komutu çalıştırın:

Install-Package BarCode

Alternatif olarak, .NET CLI'yi kullanın:

dotnet add package BarCode

Her iki komut da NuGet.org'dan mevcut sürümü çeker ve derlemeye bağlı referansı proje dosyanıza ekler. Kütüphane, .NET Framework 4.6.2'den .NET 10'a kadar, herhangi bir ek uyumluluk katmanı olmadan .NET Standard 2.0'ı hedefler.

Yükledikten sonra, herhangi bir IronBarcode yöntemini çağırmadan önce lisans anahtarınızı ayarlayın. Geliştirme ve değerlendirme için, ücretsiz bir deneme anahtarı, IronBarcode lisanslama sayfasından mevcuttur:

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

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Kapsüllü dağıtımlar için, IronBarcode, Docker ile Linux üzerinde çalışır ve bulut işlevlerinde, AWS Lambda ve Azure Functions desteklerini sunar.

Taradığınız Barkodları IronBarcode ile Nasıl Doğrularsınız?

Format Doğrulaması İçin Doğru Yaklaşım Hangisidir?

IronBarcode, 30'dan fazla barkod simgolojisini destekler, Kod 128, EAN-13, Kod 39, QR kodları ve Data Matrix dahil. USB tarayıcı uygulamaları için, doğrulama deseni, taranan dizeyi bir barkod resmi olarak yeniden şifreler ve derhal dekoder aracılığıyla geri okur. Bu, dizinin beyan edilen format için geçerli bir değer olduğunu doğrular:

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; } = "";
}
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; } = "";
}
Imports System
Imports System.Linq
Imports System.Threading.Tasks

Public Class BarcodeValidator
    Public Async Function ValidateAsync(scannedText As String, Optional preferredFormat As BarcodeEncoding = BarcodeEncoding.Code128) As Task(Of ValidationResult)
        Dim result As New ValidationResult With {.RawInput = scannedText}

        Try
            Dim barcode = BarcodeWriter.CreateBarcode(scannedText, preferredFormat)
            Dim readResults = Await BarcodeReader.ReadAsync(barcode.ToBitmap())

            If readResults.Any() Then
                Dim 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."
            End If
        Catch ex As Exception
            result.IsValid = False
            result.Error = ex.Message
        End Try

        Return result
    End Function
End Class

Public Class ValidationResult
    Public Property RawInput As String = ""
    Public Property IsValid As Boolean
    Public Property Format As BarcodeEncoding
    Public Property Value As String = ""
    Public Property Confidence As Single
    Public Property Error As String = ""
End Class
$vbLabelText   $csharpLabel

Tedarik zinciri uygulamalarında kullanılan GS1-128 barkodları için, taranan dizi, uygulama tanımlayıcı öneklerini parantez içinde içerir, örneğin GTIN için (01) ve son kullanma tarihi için (17). IronBarcode, BarcodeEncoding.GS1_128 belirttiğinizde bu uygulama tanımlayıcılarını otomatik olarak işler.

Geliştiriciler Hangi EAN-13 Checksum Mantığını Uygulamalıdır?

Perakende satış noktası uygulamaları genellikle bir değer fiyat araması yapmadan önce EAN-13 kontrol hanelerini bağımsız olarak doğrulamalıdır. EAN-13 için Luhn tarzı kontrol hattı, ilk 12 basamak boyunca 1 ve 3 ağırlıklarını değiştirir:

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');
}
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');
}
Public Shared Function ValidateEan13Checksum(value As String) As Boolean
    If value.Length <> 13 OrElse Not value.All(AddressOf Char.IsDigit) Then
        Return False
    End If

    Dim sum As Integer = 0
    For i As Integer = 0 To 11
        Dim digit As Integer = AscW(value(i)) - AscW("0"c)
        sum += If(i Mod 2 = 0, digit, digit * 3)
    Next

    Dim expectedCheck As Integer = (10 - (sum Mod 10)) Mod 10
    Return expectedCheck = (AscW(value(12)) - AscW("0"c))
End Function
$vbLabelText   $csharpLabel

Bu saf mantıksal kontrol, yüksek hacimli bir perakende ortamında her taramada yuvarlak yol görüntü oluşturma maliyetini önlemek için şifrelemeden önce çalışır. GS1 spesifikasyonu na göre, kontrol hanesi algoritması, önde gelen sıfırı düşürdüğünüzde UPC-A (12 basamak) için aynıdır.

Taranan Girdiden Yanıt Barkodlarını Nasıl Oluşturursunuz?

Bir Uygulama Bir Taramanın Ardından Ne Zaman Yeni Barkodlar Oluşturmalıdır?

Depo teslim alma biriminin ortak bir deseni "tara ve yeniden etiketle" iş akışıdır: Gelen bir ürün bir tedarikçi barkodu taşır (genellikle EAN-13 veya ITF-14) ve depo yönetim sistemi, kendi konum ve parti kodlarıyla bir içsel Kod 128 etiketi yazdırmalıdır. IronBarcode'un oluşturma yetenekleri bunu birkaç satırda halleder:

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;
    }
}
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;
    }
}
Imports System.IO
Imports System.Threading.Tasks

Public Class InventoryLabelGenerator
    Private ReadOnly _outputDirectory As String

    Public Sub New(outputDirectory As String)
        _outputDirectory = outputDirectory
        Directory.CreateDirectory(_outputDirectory)
    End Sub

    Public Async Function GenerateLabelAsync(internalCode As String, locationCode As String) As Task(Of String)
        Dim fullCode As String = $"{internalCode}|{locationCode}|{DateTime.UtcNow:yyyyMMdd}"

        ' Primary Code 128 label for scanners
        Dim 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
        Dim qrCode = BarcodeWriter.CreateQrCode(fullCode)
        qrCode.ResizeTo(200, 200)
        qrCode.SetMargins(8)

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

        Await Task.Run(Sub()
                           linearBarcode.SaveAsPng(pngPath)
                           linearBarcode.SaveAsPdf(pdfPath)
                       End Sub)

        Return pngPath
    End Function
End Class
$vbLabelText   $csharpLabel

PDF olarak kaydetme, bir paylaşımlı ağ üzerinden PDF girdi kabul eden etiket yazıcıları için özellikle yararlıdır. Ayrıca SVG olarak dışa aktarabilir ve vektör kalitesinde termal etiket çıktısı için veya bir bayt akışı olarak dışa aktarabilir ve doğrudan bir etiket yazıcı API'sine gönderebilirsiniz.

IronBarcode, kapsamlı stil özelleştirme dahil olmak üzere özel renkler, kenar boşluğu ayarlamaları, insan tarafından okunabilir metin yer arayüzleri ve QR kodları için marka işaretli mobil etiketler için logo yerleştirme destekler.

Windows Forms uygulama arayüzü, IronBarcode'un çift barkod oluşturma yeteneklerini gösteriyor. Arayüz, envanter sayısı 'INV-20250917-helloworld' için bir Kod 128 lineer barkod ve bir QR kodunun başarıyla oluşturulduğunu gösterir. Üstteki giriş alanı, kullanıcıların özel envanter kodları girmesine izin verir, 'Oluştur' düğmesi barkodları oluşturmak için basılır. Başarılı işlem 'Öğe başarıyla işlendi - Üretilen Etiketler' mesajı operasyonun tamamlandığını onaylar. Kod 128 barkodu, birincil envanter izleme formatı olarak, QR kodu ise mobil uyumlu bir alternatif olarak etiketlenmiştir. Uygulama, profesyonel bir gri arka plan kullanır ve nasıl net bir görsel hiyerarşi sağlandığını gösterir. IronBarcode, geliştiricilere eksiksiz envanter yönetimi için çok formatlı barkod oluşturma sistemleri oluşturma yeteneği sağlar.

Nasıl Tam Yüksek Hacimli Tarama Uygulaması İnşa Edilir?

Üretim Kuyruk Tabınlı Bir Uygulama Nasıl Görünür?

Dakikada düzinelerce tarama işleyen uygulamalar için, kullanıcı arayüzü iş parçacığını üzerindeki basit senkron işleyici darboğaz haline gelir. Aşağıdaki desen, tarama yakalamayı bir ConcurrentQueue<t> ve bir arka plan işleme döngüsü kullanarak işlemden ayırır. IronBarcode'ın async API'si UI'yi engellemeden doğrulamayı yönetir:

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.Dengeli,
            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);
    }
}
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.Dengeli,
            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);
    }
}
Imports IronBarCode
Imports System.Collections.Concurrent
Imports System.Threading

Public Partial Class HighVolumeScanner
    Inherits Form

    Private ReadOnly _scanQueue As New ConcurrentQueue(Of (Data As String, Timestamp As DateTime))()
    Private ReadOnly _semaphore As SemaphoreSlim
    Private ReadOnly _cts As New CancellationTokenSource()
    Private _scanner As IScannerInput

    Public Sub New()
        InitializeComponent()
        IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
        _semaphore = New SemaphoreSlim(Environment.ProcessorCount)
        InitializeScanner()
        _ = RunProcessingLoopAsync()
    End Sub

    Private Sub InitializeScanner()
        _scanner = If(System.IO.Ports.SerialPort.GetPortNames().Any(),
                      New SerialPortScanner("COM3", 115200),
                      New KeyboardWedgeScanner(txtScannerInput))

        AddHandler _scanner.BarcodeScanned, Sub(_, barcode)
                                                _scanQueue.Enqueue((barcode, DateTime.UtcNow))
                                            End Sub

        _scanner.StartListening()
    End Sub

    Private Async Function RunProcessingLoopAsync() As Task
        While Not _cts.Token.IsCancellationRequested
            Dim scan As (Data As String, Timestamp As DateTime)
            If _scanQueue.TryDequeue(scan) Then
                Await _semaphore.WaitAsync(_cts.Token)
                _ = Task.Run(Async Function()
                                 Try
                                     Await ProcessScanAsync(scan.Data, scan.Timestamp)
                                 Finally
                                     _semaphore.Release()
                                 End Try
                             End Function, _cts.Token)
            Else
                Await Task.Delay(10, _cts.Token)
            End If
        End While
    End Function

    Private Async Function ProcessScanAsync(rawData As String, scanTime As DateTime) As Task
        Dim options As New BarcodeReaderOptions With {
            .Speed = ReadingSpeed.Dengeli,
            .ExpectMultipleBarcodes = False,
            .ExpectBarcodeTypes = BarcodeEncoding.Code128 Or BarcodeEncoding.QRCode,
            .MaxParallelThreads = 1
        }

        Dim testBarcode = BarcodeWriter.CreateBarcode(rawData, BarcodeEncoding.Code128)
        Dim results = Await BarcodeReader.ReadAsync(testBarcode.ToBitmap(), options)

        If results.Any() Then
            Dim item = results.First()
            BeginInvoke(Sub() UpdateInventoryDisplay(item.Value, scanTime))
        Else
            BeginInvoke(Sub() LogRejectedScan(rawData, scanTime))
        End If
    End Function

    Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
        _cts.Cancel()
        _scanner.StopListening()
        MyBase.OnFormClosing(e)
    End Sub
End Class
$vbLabelText   $csharpLabel

SemaphoreSlim, eşzamanlı doğrulama görevlerini mantıksal işlemci sayısıyla sınırlar ve dalgalı tarama olayları sırasında kontrolsüz iş parçacığı oluşturulmasını engeller. BeginInvoke çağrıları, UI güncellemelerini ana iş parçacığına güvenli bir şekilde yeniden yönlendirir.

Farklı Tarama Hacimleri İçin Performansı Nasıl Ayarlarsınız?

BarcodeReaderOptions.Speed özelliği ReadingSpeed.Faster, ReadingSpeed.Balanced ve ReadingSpeed.Detailed kabul eder. Dizgi değerinin zaten bilindiği USB tarayıcı girişi için, Balanced uygundur -- kod çözücü yalnızca formatı doğrulamalı, bir görüntüde barkod bulmamalıdır. IronBarcode'un okuma hızı belgelerine göre, Faster modu bazı bozulma düzeltme algoritmalarını atlar, bu temiz tarayıcı çıktısı için güvenlidir ancak görüntü tabanlı senaryolarda zarar görmüş barkodları kaçırabilir.

Aşağıdaki tablo, her hız modunun ne zaman kullanılacağını özetlemektedir:

IronBarcode okuma hızı modları ve uygun kullanım durumları
Hız Modu En İyi İçin Takas
Daha hızlı Temiz USB tarayıcı girişi, yüksek hacimli aktarım Kötü hasarlı veya eğik barkodları kaçırabilir
Dengeli Karışık girdi - USB tarayıcı artı görüntü içe aktarımları Orta CPU kullanımı, iyi doğruluk
Detaylı Hasarlı etiketler, düşük kontrast baskı, PDF içe aktarımları Daha yüksek CPU kullanımı, en yavaş çıktı

Ayrıca görüntüleri veya PDF'leri USB tarayıcı girdisiyle birlikte işleyen uygulamalar için IronBarcode, PDF belgelerinden barkod okuyabilir ve aynı API yüzeyini kullanarak çok sayfalı TIFF dosyaları okuyabilir.

Profesyonel Windows Forms barkod tarayıcı uygulaması, IronBarcode'un gerçek zamanlı envanter izleme yeteneklerini gösteriyor. Arayüz, sofistike koyu mavi başlığa sahip temiz iki panel tasarımı içerir. Sol panel, dört başarılı taranmış envanter öğesi (INV-001'den INV-004'e) ile kesin zaman damgaları ve tarama durum göstergeleri içeren bir tarama geçmiş listesi gösterir. Her öğe, barkod türü ve güven düzeyi gibi ayrıntılı meta verileri içerir. Sağ panel, 'Öğeler: 4' ifadesini profesyonel stil ve uygun kenar boşluklarıyla gösteren dinamik bir şekilde oluşturulmuş özet barkodu gösterir. Envanter yönetimi için tam aksiyon düğmeleri, 'Listeyi Temizle', 'Verileri Dışa Aktar' ve 'Etiketleri Yazdır' içerir. Durum çubuğu 'Tarayıcı: Bağlı | Modu: Kesintisiz | Son Tarama: 2 saniye önce', uygulamanın gerçek zamanlı izleme yeteneklerini ve üretime hazır kurumsal profesyonel tasarımını gösteriyor. IronBarcode, üretim envanter sistemleri için etkinleştirir.

Tarayıcı Uygulamalarında Kenar Durumları ve Hataları Nasıl Ele Alırsınız?

Geliştiricilerin Hangi Hata Modlarını Tahmin Etmeli?

USB tarayıcı uygulamaları tahmin edilebilir şekillerde başarısız olur. En yaygın sorunlar ve bunların önlemleri şunlardır:

Tarayıcı bağlantısı kesilmesi -- Bir USB tarayıcı çekildiğinde, klavye kama TextBox sanal klavyesini kaybeder. En basit önlem, periyodik bir zamanlayıcı olup, _inputBox.Focused kontrol eder ve tarayıcı hala bağlı HID cihazları listesinde ise yeniden odaklar. Seri tarayıcılar için, SerialPort.GetPortNames() yeniden bağlanmayı algılar.

Belirsiz barkod formatları -- Bazı ürünler, birden fazla simgolojide geçerli olan barkodları taşır. Örneğin, 12 basamaklı bir dizi hem geçerli bir UPC-A hem de geçerli bir Code 128'dir. ExpectBarcodeTypes belirtmek BarcodeReaderOptions içinde kod çözücüyü beklenen formatlarınıza sınırlar ve belirsizliği ortadan kaldırır. IronBarcode sorun giderme kılavuzu, formata özgü tanıma ipuçlarını kapsar.

Geçersiz format istisnaları -- BarcodeWriter.CreateBarcode seçili kodlama kurallarını ihlal eden bir dizi alırsa (örneğin, yalnızca sayısal EAN-13 alanında alfabetik karakterler) bir IronBarCode.Exceptions.InvalidBarcodeException fırlatır. Tekrarlama çağrısını bir try-catch içinde sararak sadece dize doğrulama yoluna geri dönülür ve uygulamanın çalışması sağlanır.

Tuş vuruşu zamanlama çarpışmaları -- Aynı TextBox'a operatörlerin manuel olarak yazdığı ortamlarda, daha önce açıklanan patlama zamanlayıcısı yaklaşımı birincil savunmadır. İkincil bir koruma, minimum uzunluktur: Çoğu gerçek barkod en az 8 karakterdir, bu nedenle bundan daha kısa dizeler klavye girişi gibi muamele görebilir.

System.IO.Ports.SerialPort ile ilgili Microsoft .NET belgelendirmesi, özellikle ReadTimeout ve WriteTimeout ayarları çevresinde, seri tarayıcı bağlantı sorunlarını giderirken yararlıdır. Perakende düzenlemelerine uyum sağlamak için GS1 Genel Spesifikasyonları, her uygulama tanımlayıcısı için geçerli değer aralıklarını tanımlar.

Uygulamayı Mobil ve Web Platformlarına Nasıl Genişletirsiniz?

Yukarıda gösterilen tarayıcı arayüzü deseni -- IScannerInput ile BarcodeScanned olay -- donanımı işleme mantığından soyutlar. Uygulamalar arasındaki geçiş aynı doğrulama ve üretim kodunun farklı platformlarda çalışmasına imkan tanır:

  • .NET MAUI, mobil alım istasyonları olarak kullanılan Android ve iOS tabletler için kamera tabanlı tarayıcı uygulaması sağlar
  • Blazor Server, tarayıcı tabanlı taramayı, JavaScript kamera erişimi ile aynı BarcodeScanned etkinliğine besleme ile destekler.
  • Android ve iOS yerel uygulamaları, mobil geliştiriciler için arka planda aynı IronBarcode dekoder ile kamera tarama yeteneği sağlar

Buluta özgü mimariler için, doğrulama ve etiket üretim adımları kuyruğundaki ileti tetiklemeleriyle çalışan Azure İşlevleri gibi hale gelebilir, masaüstü uygulaması sadece tarayıcı giriş kapısı olarak çalışır. Bu ayrım, etiket basma mantığının uyum denetimleri için merkezileştirilmesi gerektiğinde özellikle yararlıdır.

Sonraki Adımlarınız Neler?

IronBarcode ile USB barkod tarayıcı uygulaması oluşturmak, klavye kama girdisini patlama zamanlaması algılamayla yakalamak, taranan değeri IronBarcode'un dekoderi aracılığıyla doğrulamak, gerekli formatta yanıt etiketler oluşturmak ve eşzamanlı bir kuyruğa sahip yüksek tarama hacimli işlemlerle dört somut aşama içerir. Her aşama bağımsızdır ve izole olarak test edilebilir.

Buradan, uygulamayı toplu işlem senaryoları için çoklu barkod okuması, görüntü bazlı girdiler için kırpılmış alan iyileştirmesi veya eski depo ekipmanları için MSI barkod desteği ile genişletmeyi düşünün. IronBarcode belgeleri, tüm desteklenen formatları ve gelişmiş okuyucu yapılandırma seçeneklerini kapsar.

Ücretsiz bir denemeye başlayın, geliştirme lisans anahtarı alarak IronBarcode'u tarama uygulamanıza entegre etmeye başlayın.

Sıkça Sorulan Sorular

IronBarcode nedir ve USB barkod tarayıcıları ile nasıl ilişkilidir?

IronBarcode, geliştiricilerin USB barkod tarama için sağlam C# uygulamaları oluşturmasına olanak tanıyan bir kütüphanedir. Barkod geçerliliği, veri çıkarımı ve barkod oluşturma gibi özellikler sunar.

IronBarcode USB tarayıcıdan gelen barkod verilerini doğrulayabilir mi?

Evet, IronBarcode, USB tarayıcıdan alınan barkod verilerini doğrulayabilir, bu da C# uygulamalarınızda veri bütünlüğü ve doğruluğu sağlar.

IronBarcode barkod oluşturmayı nasıl halleder?

IronBarcode, geliştiricilerin C# uygulamalarında kolayca barkod oluşturmasına ve yazdırmasına olanak tanıyan yeni barkodlar oluşturabilir.

USB barkod tarama için IronBarcode'da hata işleme desteği var mı?

Evet, IronBarcode, USB barkod tarama ve işleme sırasında ortaya çıkabilecek yaygın sorunları yönetmek için kapsamlı hata işleme içerir.

Hangi tipte barkodlar IronBarcode ile taranabilir?

IronBarcode, QR kodları, UPC, Code 39 ve daha fazlasını içeren geniş bir barkod semboloji yelpazesinin taranmasını destekler ve bu da onu çeşitli uygulamalar için çok yönlü kılar.

IronBarcode taranmış barkodlardan yapısal bilgi çıkarabilir mi?

Evet, IronBarcode taranmış barkodlardan yapısal bilgi çıkarabilir, bu da verimli veri işleme ve yönetimine yardımcı olur.

C#'ta bir USB barkod tarayıcı uygulaması oluşturmaya nasıl başlayabilirim?

C#'ta bir USB barkod tarayıcı uygulaması oluşturmaya başlamak için, IronBarcode'u sağlanan kod örnekleri ve belgelerle birlikte kullanarak geliştirme sürecine rehberlik edebilirsiniz.

Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında Lisans Derecesine (Carleton Üniversitesi) sahip ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirmeyle ilgileniyor. Sezgisel ve estetik açıdan hoş kullanıcı arayüzleri oluşturma tutkunu, Curtis modern çerçevelerle çalışmayı ve iyi yapı...

Daha Fazla Oku

Iron Destek Ekibi

Haftada 5 gün, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara