C# 按键事件处理程序,但在没有窗体的windows应用程序上

C# 按键事件处理程序,但在没有窗体的windows应用程序上,c#,C#,我有一个与读卡器(磁条)相连的应用程序。当我有一个输出数据的表单或者在一个控制台应用程序中可以将数据输出到控制台时,我能够捕获卡上的数据 但在我正在开发的应用程序中,它有一个程序类作为启动程序,并以这种方式启动程序 我想我需要的是一个通用的按键侦听器,以便在刷卡时查找 我想我需要像KeyPressEventHandler这样的东西,但我的应用程序中似乎无法实现这一点 我创建了以下扩展方法: public static class Utilities { private static

我有一个与读卡器(磁条)相连的应用程序。当我有一个输出数据的表单或者在一个控制台应用程序中可以将数据输出到控制台时,我能够捕获卡上的数据

但在我正在开发的应用程序中,它有一个程序类作为启动程序,并以这种方式启动程序

我想我需要的是一个通用的按键侦听器,以便在刷卡时查找

我想我需要像KeyPressEventHandler这样的东西,但我的应用程序中似乎无法实现这一点

我创建了以下扩展方法:

public static class Utilities
{
    private static KeyPressEventHandler handler = KeyPressed;

    public static void KeyPressed(Object sender, KeyPressEventArgs e)
    {
        while (true)
        {
            dataReceived.Append(e.KeyChar);
        }
    }

    public static KeyPressEventHandler getKeyPressHandler()
    {
        return handler;
    }
}
但是我不确定如何在我的
Main()
方法中引用它。我没有看到按键的方法

一个示例(自.net framework 1.1以来我没有更新代码),在按下任何键时都会发生事件:


根据CLR和Windows的版本,您在使用Windows钩子时会遇到一些特定的问题

  • WH_键盘/WH_键盘所有键盘挂钩需要一个消息循环才能正常工作。在生成对钩子委托的调用之前,键盘事件被发布到安装线程的消息队列中
  • Windows Vista及更高版本将不允许低权限进程的挂钩查看高权限进程中的活动。因此,根据当前具有输入焦点的进程,您可能会或可能不会获得键盘事件
  • 钩住键盘事件后,您将需要读卡器生成开始和停止sentinel,以指示您应该捕获剩余的输入。这是否可以实现取决于配置读卡器的能力
  • 话虽如此,使用WHU键盘或WHU键盘挂钩当然可以达到预期的效果。如果您决定这样做,我建议您使用交替的左Ctrl键和右Control键作为来自读卡器的开始和停止哨兵(假设它能够这样做)

    此外,如果您最终使用了Windows钩子,则需要从后台线程而不是应用程序的主线程安装钩子,因为您需要在一定时间内处理键盘事件。如果您花费的时间超过Windows允许的时间,钩子将被忽略

    作为Windows钩子的替代方法,您可以使用DirectInput。老实说,我从未尝试过这种方法,但这个概念似乎是合理的,并且消除了Windows挂钩的一些不确定性

    我假设,因为您要求全局键盘事件,所以您的读卡器是某种类型的USB HID设备。您可以通过运行DxDiag验证读卡器是否显示为DirectInput设备。如果可以访问该设备,则该设备应显示在“输入”选项卡上。DirectX似乎有各种可用的托管程序集

    如果您不局限于现有的读卡器类型,那么最好使用基于串行的读卡器。有了它,您将无法完成设备输出的其他应用程序

    我意识到我实际上并没有回答你们的问题,所以请随意否决投票或忽略这个答案。希望这确实给了你一些关于你可能面临的问题的信息

    经过进一步思考,我认为您可以直接访问HID设备,并使用标准Win32 API执行键盘翻译。沿着这条路线看,我遇到了API。使用此功能,您应该能够注册所有键盘设备的原始输入,然后在输入时确定实际生成事件的设备。无需从读卡器启动和停止哨兵

    更好的是,API发送消息来区分窗口是前台窗口时生成的输入和窗口不是前台窗口时生成的输入。有了这个API,您仍然需要在后台线程上创建一个窗口和消息循环,但是它应该比Windows钩子方法干净得多


    请参见CodeProject上的示例应用程序,该应用程序读取C#中的原始输入。

    您需要一个窗口来捕获密钥,或者您应该查看
    SetWindowsHook
    @JeroenvanLangen-您有没有关于如何在C#中执行此操作的示例?@webdad3您是否尝试过一个著名的网站,并提供了大量示例:?@BartoszKP-我整天都在寻找示例。但我明白你的意思。我今天累了。@webdad3提高编码性能的最好办法是休息一下,散散步;)也许这会有帮助:?
    public class Hook
    {
    
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();
    
        public static event Action Event = null;
        private const int WH_KEYBOARD = 2;
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static int _hookKeyboard = 0;
        private static HookProc _hookKeyboardProc;
    
        public static bool Install() 
        {
            _hookKeyboardProc = new HookProc(KeyboardHook);
            _hookKeyboard = SetWindowsHookEx(WH_KEYBOARD, _hookKeyboardProc, IntPtr.Zero, GetCurrentThreadId());
            return _hookKeyboard != 0;
        }
    
        public static bool Uninstall()
        {
            // uninstall keyboard hook
            if(!UnhookWindowsHookEx(_hookKeyboard))
                return false;
            _hookMouseProc = null;
            return true;
        }
    
        private static int KeyboardHook(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // if any message - fire event
            if(nCode >= 0 && Event != null) 
                Event();
            return CallNextHookEx(_hookKeyboard, nCode, wParam, lParam); 
        }
    }