You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下用C# .NET7实现后台读取条码扫描器数据问询

解决方案说明

一、浏览器JavaScript无法实现需求

  • 浏览器的安全沙箱限制了JS直接访问系统硬件或拦截全局输入事件,即便输入框设置了autofocus,只要浏览器不是前台窗口,系统就会将键盘输入导向当前活跃的前台应用,JS完全无法捕获后台状态下的USB设备输入。
  • 因此必须依赖桌面端程序实现后台输入拦截与转发。

二、基于C# .NET7的可行方案

针对你的场景,推荐使用RawInput API结合后台服务/系统托盘应用的方案,以下是具体实现思路:

1. RawInput API的C#封装与使用

RawInput可直接识别特定USB设备的输入,不会被前台窗口抢占,核心步骤:

  • 通过P/Invoke封装RawInput相关Win32 API(如RegisterRawInputDevices、GetRawInputData等)。
  • 注册监听目标USB条码扫描器(通过设备的VID/PID筛选,避免捕获普通键盘输入)。
  • 在后台隐藏窗口中处理RawInput消息,解析条码数据。
  • 解析完成后,通过HTTP请求将条码数据发送到/authenticate接口,替代浏览器表单提交逻辑。

2. 后台运行的实现方式

  • 系统托盘应用:用.NET7的Windows Forms或WPF创建带托盘图标的应用,启动后隐藏主窗口,在后台监听RawInput事件,适合需要用户交互(如设置设备、查看日志)的场景。
  • Windows服务+辅助进程:纯服务无法直接处理RawInput(无交互桌面权限),需配合CreateProcessAsUser启动带桌面交互的辅助进程监听输入,适合完全无界面的后台运行场景。

3. 关键代码片段示例

(1)RawInput基础P/Invoke定义

using System.Runtime.InteropServices;

public static class RawInputNative
{
    [StructLayout(LayoutKind.Sequential)]
    public struct RAWINPUTDEVICE
    {
        public ushort UsagePage;
        public ushort Usage;
        public uint Flags;
        public IntPtr WindowHandle;
    }

    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevices, uint uiNumDevices, uint cbSize);

    // 需补充封装GetRawInputData、GetRawInputDeviceInfo等必要API
}

(2)注册目标条码扫描器

假设扫描器属于HID键盘类(Usage Page=0x01,Usage=0x06),通过VID/PID筛选设备:

// 先实现GetTargetScannerHandle方法,根据VID/PID找到目标设备句柄
IntPtr targetWindowHandle = GetHiddenWindowHandle(); // 后台隐藏窗口的句柄
var rid = new RAWINPUTDEVICE[]
{
    new RAWINPUTDEVICE
    {
        UsagePage = 0x01,
        Usage = 0x06,
        Flags = 0x00000001 | 0x00000010, // RIDEV_INPUTSINK + RIDEV_DEVNOTIFY
        WindowHandle = targetWindowHandle
    }
};

RawInputNative.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICE)));

(3)处理RawInput消息

在隐藏窗口的WndProc中捕获WM_INPUT消息并解析条码:

protected override void WndProc(ref Message m)
{
    const int WM_INPUT = 0x00FF;
    if (m.Msg == WM_INPUT)
    {
        string barcode = ParseRawInputData(m.LParam); // 实现解析按键序列为条码的逻辑
        if (!string.IsNullOrEmpty(barcode))
        {
            using var client = new HttpClient();
            var content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                { "BarCode", barcode }
            });
            _ = client.PostAsync("http://your-server-address/authenticate", content);
        }
    }
    base.WndProc(ref m);
}

三、替代方案:WH_KEYBOARD_LL全局钩子

如果RawInput的设备筛选存在困难,可使用WH_KEYBOARD_LL钩子:

  • 全局捕获键盘输入,通过扫描器的输入特征(如连续快速按键、结尾带回车)判断是否为目标条码。
  • 钩子需在有消息循环的进程中运行,系统托盘应用是合适载体,通过SetWindowsHookEx等P/Invoke实现。

内容的提问来源于stack exchange,提问作者Andrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:18:31