Altbilgi içeriğine atla
IRONBARCODE KULLANARAK

C# USB Çizgikodu Tarayıcı: Tam Bir Tarayıcı Uygulaması Oluşturun

USB barkod tarayıcılar, taranan verileri yazılı karakterler ve ardından Enter tuşu vuruşuyla gönderen standart klavye giriş cihazları olarak C# uygulamalarına bağlanır. Bu HID klavye wedge davranışı entegrasyonu kolaylaştırır -- uygulamanızda herhangi bir özel sürücü veya SDK gerekmeden metin girişi alırsınız. IronBarcode, bu ham girişi formatları doğrulamak, yapılandırılmış veriler çıkarmak ve yanıt barkodları üretmek için işler, envanter yönetimi, perakende satış noktası ve lojistik takip sistemleri için tam bir veri hattı oluşturur.

Perakende, depolama ve üretim operasyonları, doğru ve hızlı barkod taramaya bağlıdır. Bir geliştirici, bir USB tarayıcıyı Windows Forms veya WPF uygulamasına bağladığında, tarayıcı, bir klavye gibi davranır -- veri bir TextBox'a gelir ve Enter tuşuna basmak, tam bir barkodun alındığını sinyaller. Zorluk, veriyi kaydetmek değil; onu doğru bir şekilde işlemektir. IronBarcode'un barkod doğrulaması, format bütünlüğünü kontrol eder, parti numaraları veya GS1 uygulama tanımlayıcıları gibi alanları çıkarır ve hemen yanıt olarak yeni bir barkod üretebilir.

Bu kılavuz, adım adım üretim hazır bir C# USB barkod tarayıcı uygulaması oluşturmanın yolunu gösterir. Kütüphaneyi kuracak, tarayıcı girişini yakalayacak, barkod formatlarını doğrulayacak, yanıt etiketlerini üretecek ve yüksek hacimli bir sıra tabanlı işlemci kuracaksınız. Her bölüm, .NET 10'u hedefleyen ve uygun yerlerde üst düzey ifade tarzını kullanan eksiksiz, çalıştırılabilir kod içerir.

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

HID Klavye Wedge Modu Entegrasyonu Neden Kolaylaştırır?

Çoğu USB barkod tarayıcı, varsayılan olarak HID klavye wedge modunda gönderilir. Birini bir Windows makinesine taktığınızda, işletim sistemi onu hem bir USB depolama cihazı (yapılandırma için) hem de bir klavye (veri girişi için) olarak kaydeder. Bir barkod tarandığında, cihaz kodlanmış barkod değerini tuş vuruşlarına çevirir ve odaklanmış olan uygulama penceresine gönderir, sonunda taşıyıcı dönüşü ekleyerek.

Bir C# geliştiricisi olarak, bu, satıcı SDK'larına, COM kütüphanelerine veya özel USB API'lerine ihtiyaçınız olmadığı anlamına gelir. Bir KeyDown işleyicisine sahip standart bir TextBox, giriş yakalamak için gereken tek şeydir. Ana entegrasyon zorluğu, tarayıcı girdisini gerçek klavye yazısından ayırt etmektir. Tarayıcılar genellikle tüm karakterleri çok kısa bir patlama içinde iletir -- genellikle 50 milisaniyeden kısa -- insan yazımı ise tuş vuruşlarını yüzlerce milisaniye boyunca yayar. Patlamanın zamanlaması, kazara tuş vuruşlarını filtrelemenin güvenilir bir yoludur.

Profesyonel sınıf tarayıcılar ayrıca seri (RS-232 veya sanal COM port) ve doğrudan USB HID modlarını destekler, bu da size ön ek/son ek karakterler 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

Klavye kama uygulamasındaki zaman patlaması detayı anahtardır. Her tuş vuruşunda sıfırlanır ve yalnızca karakterler gelmeyi durdurduğunda çalışır -- bu, yavaş yavaş yazan gerçek klavye kullanıcılarının tamamlanmamış girdilerinin barkod taraması olarak değerlendirilmek yerine atılacağı anlamına gelir.

Çoklu Tarayıcı Markaları Nasıl Yönetilir?

Enterprise ortamları sıklıkla aynı katta bir karışım Honeywell, Zebra (eski adıyla Symbol/Motorola) ve Datalogic tarayıcıları çalıştırır. Her satıcının kendi varsayılan sonlandırıcı karakterleri, baud hızları ve önek/son ek konvansiyonları vardır. Bir yapılandırma 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 yapılandırmaları bir ayar dosyasında veya veritabanında depolamak, depo personelinin tarayıcı modellerini yeniden dağıtım gerektirmeden değiştirebileceği anlamına gelir. ScannerType alanı, başlangıçta hangi IScannerInput uygulamasının örnekleneceğini belirler.

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

NuGet Üzerinden IronBarcode Eklemek için En Hızlı Yol Nedir?

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

Install-Package IronBarCode
Install-Package IronBarCode
SHELL

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

dotnet add package IronBarCode
dotnet add package IronBarCode
SHELL

Her iki komut da mevcut sürümü NuGet.org'dan çeker ve derleme referansını proje dosyanıza ekler. Kütüphane .NET Standard 2.0'ı hedefler, böylece .NET Framework 4.6.2'den .NET 10'a kadar ek uyumluluk dolgu gerektirmeden çalışır.

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

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

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

Konteynerleştirilmiş dağıtımlar için, IronBarcode Docker ile Linux'ta çalışır ve bulut fonksiyonları için AWS Lambda ve Azure Fonksiyonları desteklenir.

Tarama Barkodları IronBarcode ile Nasıl Doğrulanır?

Format Doğrulama İçin Doğru Yaklaşım Nedir?

IronBarcode 30'dan fazla barkod sembolojisini destekler bunlar arasında Code 128, EAN-13, Code 39, QR kodları ve Data Matrix bulunur. USB tarayıcı uygulamaları için doğrulama deseni, taranmış dizgiyi barkod resmi olarak yeniden kodlar ve hemen dekoder aracılığıyla okur. Bu gidiş-dönüş, dizginin bildirilen 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 dize parantez içinde uygulama tanımlayıcı ön eklerini 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 ayrıştırır.

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

Perakende satış noktası uygulamaları genellikle EAN-13 kontrol rakamlarını fiyat sorgulamasına geçmeden önce bağımsız olarak doğrulama gerektirir. EAN-13 için Luhn tarzı kontrol toplamı, 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 tarama için gidiş-dönüş resim oluşturma yükünü önlemek amacıyla kodlamadan önce çalışır. GS1 spesifikasyonuna göre, kontrol rakamı algoritması UPC-A (12 haneli) için lider sıfırı bıraktığınızda aynıdır.

Taranan Girdiden Yanıt Barkodları Nasıl Üretilir?

Bir Uygulama Taramadan Sonra Ne Zaman Yeni Barkod Üretmelidir?

Depo alımında yaygın bir desen 'tara ve etiketle' iş akışıdır: gelen bir öğe bir tedarikçi barkodu taşır (genellikle EAN-13 veya ITF-14) ve depo yönetim sistemi kendi konumu ve parti kodları ile bir iç Code 128 etiketini yazdırmalıdır. IronBarcode'un oluşturma yetenekleri bunu birkaç satırda işler:

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, özellikle PDF girişini bir ağ paylaşımı üzerinden kabul eden etiket yazıcıları için kullanışlıdır. Ayrıca, SVG olarak dışa aktarabilirsiniz vektör kalitesinde termal etiket çıktısı için veya etiket yazıcı API'sine doğrudan göndermek üzere bir bayt akışı olarak dışa aktarabilirsiniz.

IronBarcode geniş stil özelleştirmelerini destekler; özel renkler, kenar boşluğu ayarlamaları, okunabilir metin eklemeleri ve QR kodları için logo gömme markalı mobil etiketler için.

Windows Forms uygulama arayüzü, IronBarcode'un çift barkod oluşturma yeteneklerini gösteriyor. Arayüz, envanter numarası 'INV-20250917-helloworld' için hem bir Code 128 doğrusal barkod hem de QR kodunun başarılı bir şekilde oluşturulduğunu gösterir. Üstteki giriş alanı, kullanıcıların özel envanter kodları girmesine olanak tanır ve barkodları oluşturmak için bir 'Oluştur' düğmesi bulunur. 'Öğe başarıyla işlendi - Üretilen Etiketler' başarı mesajı, işlemin tamamlandığını doğrular. Code 128 barkodu, birincil envanter izleme formatı olarak etiketlenirken alttaki QR kodu mobil dostu bir alternatif olarak işaretlenmiştir. Uygulama, profesyonel bir gri arka plana sahiptir ve net bir görsel hiyerarşi sunar; bu, IronBarcode'un geliştiricilere komple envanter yönetimi için çok formatlı barkod oluşturma sistemleri oluşturma sağladığını gösterir.

Yüksek Hacimli Tam Bir Tarama Uygulaması Nasıl Kurulur?

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

Dakikada düzinelerce taramayı işleyen uygulamalar için, UI iş parçacığında basit bir senkron işleyici dar boğaz olur. Aşağıdaki desen, tarama yakalama işlemini bir ConcurrentQueue<t> ve bir arka plan işleme döngüsü kullanarak işlemden ayırır. IronBarcode'un eşzamansız API'si doğrulamayı UI'yi engellemeden gerçekleştirir:

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, mantıksal işlemci sayısını eşzamanlı doğrulama görevlerine sınırlar, ani tarama olaylarında aşırı iş parçacığı oluşturulmasını önler. BeginInvoke, UI güncellemelerini güvenli bir şekilde ana iş parçacığına geri yönlendirir.

Değişken Tarama Hacimleri İçin Performans Nasıl Ayarlanır?

BarcodeReaderOptions.Speed özelliği, ReadingSpeed.Daha hızlı, ReadingSpeed.Dengeli ve ReadingSpeed.Detaylı kabul eder. Dize değerinin zaten bilindiği USB tarayıcı girişi için, Dengeli uygundur -- kod çözücü yalnızca formatı doğrulamalı, bir görüntüde barkod aramamalıdır. IronBarcode'un okuma hızı belgelerine göre, Daha hızlı modu bazı bozulma düzeltme algoritmalarını atlar, bu temiz tarayıcı çıkışı için güvenlidir, ancak görüntü tabanlı senaryolarda hasarlı barkodları kaçırabilir.

Aşağıdaki tablo, her hız modunu ne zaman kullanacağınızı özetlemektedir:

IronBarcode okuma hız modları ve uygun kullanım senaryoları
Hız Modu En İyi Kullanım Amacı Takas
Daha hızlı Temiz USB tarayıcı girişi, yüksek hacimli çıktı Kötü hasar görmüş veya eğik barkodları gözden kaçırabilir
Dengeli Karışık giriş -- USB tarayıcı ve görüntü ithalatları Orta CPU kullanımı, iyi doğruluk
Detaylı Hasar görmüş etiketler, düşük kontrastlı baskılar, PDF girişleri Daha yüksek CPU kullanımı, en yavaş çıktı

USB tarayıcı girişine ek olarak görüntü veya PDF işleyen uygulamalar için, IronBarcode, PDF belgelerinden barkodları okuyabilir ve çok sayfalı TIFF dosyaları aynı API yüzeyi kullanılarak.

Profesyonel Windows Forms barkod tarayıcı uygulaması, IronBarcode'un gerçek zamanlı envanter izleme yeteneklerini sergiliyor. Arayüz, sofistike bir koyu mavi başlık ile temiz bir iki panel tasarımına sahiptir. Sol panel, dört başarılı taranmış envanter öğesi (INV-001'den INV-004'e kadar) gösteren bir tarama geçmişi listesi içerir, kesin zaman damgaları ve tarama durumu göstergeleri içerir. Her öğe, barkod türü ve güven seviyesi gibi detaylı meta verileri içerir. Sağdaki panel, profesyonel tasarım ve uygun kenar boşlukları ile 'Öğeler: 4' gösteren dinamik olarak oluşturulmuş bir özet barkod gösterir. Alt kısımdaki eylem düğmeleri, kapsamlı envanter yönetimi için 'Listeyi Temizle', 'Veriyi Dışa Aktar' ve 'Etiketleri Yazdır' seçeneklerini içerir. Durum çubuğu 'Tarayıcı: Bağlandı| Mod: Sürekli| Son Tarama: 2 saniye önce', uygulamanın gerçek zamanlı izleme yeteneklerini ve IronBarcode'un prodüksiyon envanter sistemleri için olan profesyonel şirket hazır tasarımını gözler önüne seriyor.

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

Geliştiriciler Hangi Arıza Modlarını Tahmin Etmelidir?

USB tarayıcı uygulamaları öngörülebilir yollarla başarısız olur. En yaygın sorunlar ve hafifletmeleri şunlardır:

Tarayıcı bağlantısının kesilmesi -- Bir USB tarayıcı çıkarıldığında, klavye kama TextBox'u sanal klavyesini kaybeder. En basit önlem, _inputBox.Focused kontrol eden ve tarayıcı hala bağlı HID aygıtları listesinde yer alıyorsa onu yeniden odaklayan periyodik bir zamanlayıcıdır. Seri tarayıcılar için, SerialPort.GetPortNames() yeniden bağlanmayı algılar.

Belirsiz barkod formatları -- Bazı ürünler birden fazla sembolojide geçerli barkodlar taşır. Örneğin, 12 basamaklı bir dize geçerli bir UPC-A'dir ve aynı zamanda geçerli bir Kod 128'dir. BarcodeReaderOptions'de ExpectBarcodeTypes belirtmek, kod çözücüyü beklenen formatlarınıza kısıtlar ve belirsizliği ortadan kaldırır. IronBarcode sorun giderme kılavuzu, format özelinde tanıma ipuçlarını kapsar.

Geçersiz format istisnaları -- Eğer BarcodeWriter.CreateBarcode seçilen kodlamanın kurallarını ihlal eden bir dize alırsa (örneğin, yalnızca sayısal EAN-13 alanında alfabetik karakterler), bir IronBarCode.Exceptions.InvalidBarcodeException fırlatır. Çağrıyı try-catch içinde sarmak ve sadece dizgi doğrulama yoluna düşmek uygulamanın çalışmaya devam etmesini sağlar.

Tuş vuruşu zamanlama çakışmaları -- Operatörlerin aynı TextBox'a elle yazdığı ortamlarda, önceki açıklanan patlama timer yaklaşımı birincil savunmadır. İkincil bir savunma minimum uzunluktur: çoğu gerçek barkod en az 8 karakter uzunluğundadır, bu nedenle daha kısa dizgiler klavye girişi olarak değerlendirilebilir.

Seri tarayıcı bağlantısını giderirken System.IO.Ports.SerialPort konusundaki Microsoft .NET belgeleri özellikle ReadTimeout ve WriteTimeout ayarları etrafında faydalıdır. Perakende sektörü mevzuat uyumu için, GS1 Genel Spesifikasyonları her uygulama tanımlayıcı için geçerli değer aralıklarını tanımlar.

Uygulama Mobil ve Web Platformlarına Nasıl Genişletilir?

Yukarıda gösterilen tarayıcı arayüz deseni -- IScannerInput ve BarcodeScanned olayı ile -- donanımı işleme mantığından soyutlar. Uygulama değişiklikleri, aynı doğrulama ve oluşturma kodunun farklı platformlarda çalışmasına izin verir:

  • .NET MAUI, mobil alım istasyonu olarak kullanılan Android ve iOS tabletlerde kamera tabanlı bir tarayıcı uygulaması sağlar
  • Blazor Server, aynı BarcodeScanned etkinliğine beslenen JavaScript kamera erişimi ile tarayıcı tabanlı taramayı destekler.
  • Mobil geliştiricilere kamerayla tarama yapma olanağı veren, ancak aynı IronBarcode deşifreleyiciye sahip olan Android ve iOS yerel uygulamaları

bulut tabanlı mimariler için, doğrulama ve etiket oluşturma adımları yalnızca tarayıcı girişi geçişi yapan masaüstü uygulaması olarak bir Azure Fonksiyonları olarak çalıştırılabilir. Bu ayrım, özellikle etiket yazdırma mantığı merkezileştirilmesi gerektiğinde uyumluluk denetimi açısından kullanışlıdır.

Sıradaki Adımlarınız Neler?

IronBarcode ile bir USB barkod tarayıcı uygulaması oluşturmak dört somut aşama içerir: gidip-gelme zamanlaması algılama ile klavye kama girdisini yakalamak, IronBarcode'un dekoderi ile taranan değeri doğrulamak, gerekli biçimde yanıt etiketleri oluşturmak ve eşzamanlı bir kuyrukla yüksek tarama hacimlerini işlemek. Her aşama bağımsızdır ve izole edilmiş olarak test edilebilir.

Buradan, toplu işleme senaryoları için çoklu barkod okuma, görüntü tabanlı girdiler için kırpma bölgesi optimizasyonu, veya eski depo ekipmanları için MSI barkod desteği ile uygulamayı genişletmeyi dikkate alın. IronBarcode dökümantasyonu, tüm desteklenen formatları ve gelişmiş okuyucu yapılandırma seçeneklerini kapsar.

Ücretsiz bir deneme başlatın, bir geliştirme lisans anahtarı alın ve IronBarcode'u tarayıcı uygulamanıza bugün entegre etmeye başlayın.

Sıkça Sorulan Sorular

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

IronBarcode, geliştiricilerin USB barkod taraması için sağlam C# uygulamaları oluşturmasını sağlayan bir kütüphanedir. Barkod doğrulama, veri çıkarma ve barkod oluşturma gibi özellikler sunar.

IronBarcode, USB tarayıcısından barkod verilerini doğrulayabilir mi?

Evet, IronBarcode USB tarayıcısından alınan barkod verilerini doğrulayabilir, böylece C# uygulamalarınızda veri bütünlüğünü ve doğruluğunu sağlar.

IronBarcode, barkod oluşturmayı nasıl ele alır?

IronBarcode, geliştiricilerin C# uygulamaları içinde kolayca barkod oluşturup yazdırmasına olanak tanıyan uçucu barkodlar oluşturabilir.

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

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

Hangi tur barkodlar IronBarcode ile taranabilir?

IronBarcode, QR kodlar, UPC, Code 39 ve daha fazlası dahil olmak üzere çeşitli barkod sembolojilerini taramayı destekler, bu da onu çeşitli uygulamalar için çok yönlü kılar.

IronBarcode taranmış barkodlardan yapılandırılmış bilgi çıkarabilir mi?

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

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

C# ile USB barkod tarayıcı uygulaması oluşturmaya başlamak için IronBarcode'u kullanabilir ve geliştirmenizi yönlendirmek için sağlanan kod örneklerini ve belgeleri kullanabilirsiniz.

Jordi Bardia
Yazılım Mühendisi
Jordi Python, C# ve C++ konularında en yetkin, Iron Software'deki yeteneklerini kullanmadığı zamanlarda; oyun programlıyor. Ürün testi, ürün geliştirme ve araştırma sorumluluklarını paylaşan Jordi, sürekli ürün gelişimine büyük değer katıyor. Çeşitli deneyimleri onu ...
Daha Fazlasını Oku

Iron Destek Ekibi

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