如何修复 C# 控制台应用程序中的错误 KeyEventHandler?

Posted

技术标签:

【中文标题】如何修复 C# 控制台应用程序中的错误 KeyEventHandler?【英文标题】:How to fix error KeyEventHandler in c# console application? 【发布时间】:2020-11-09 02:48:21 【问题描述】:

我有个问题,在我的winform应用程序中执行这段代码的时候,运行正常,但是在控制台运行的时候报错,好像KeyEventHandler只用在winform中,是的,可以在控制台替换什么应用。这是我的钩子函数:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace Websevice_Core_Console

class Y2KeyboardHook

    #region Win32 API Functions and Constants

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        KeyboardHookDelegate lpfn, IntPtr hMod, int dwThreadId);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    private const int WH_KEYBOARD_LL = 13;

    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x101;

    #endregion

    private KeyboardHookDelegate _hookProc;
    private IntPtr _hookHandle = IntPtr.Zero;

    public delegate IntPtr KeyboardHookDelegate(int nCode, IntPtr wParam, IntPtr lParam);

    [StructLayout(LayoutKind.Sequential)]
    public struct KeyboardHookStruct
    
        public int VirtualKeyCode;
        public int ScanCode;
        public int Flags;
        public int Time;
        public int ExtraInfo;
    

    #region Keyboard Events

    public event KeyEventHandler KeyDown;
    public event KeyEventHandler KeyUp;

    #endregion

    // destructor
    ~Y2KeyboardHook()
    
        Uninstall();
    

    public void Install()
    
        _hookProc = KeyboardHookProc;
        _hookHandle = SetupHook(_hookProc);

        if (_hookHandle == IntPtr.Zero)
            throw new Win32Exception(Marshal.GetLastWin32Error());
    
    private IntPtr SetupHook(KeyboardHookDelegate hookProc)
    
        IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);

        return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
    

    private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    
        if (nCode >= 0)
        
            KeyboardHookStruct kbStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

            if (wParam == (IntPtr)WM_KEYDOWN)
            
                if (KeyDown != null)
                    KeyDown(null, new KeyEventArgs((Keys)kbStruct.VirtualKeyCode));
            
            else if (wParam == (IntPtr)WM_KEYUP)
            
                if (KeyUp != null)
                    KeyUp(null, new KeyEventArgs((Keys)kbStruct.VirtualKeyCode));
            
        

        return CallNextHookEx(_hookHandle, nCode, wParam, lParam);
    

    public void Uninstall()
    
        UnhookWindowsHookEx(_hookHandle);
    


这是我的使用方法:

 _y2KeyboardHook.KeyDown += (sender, e) =>// ghi nhan thong tin tu ban phim
        
            if (e.KeyCode.ToString() != "")
            
               Console.WriteLine("Hello "+KeyCode);
            

       

我在 2 行收到一条错误消息

    public event KeyEventHandler KeyDown;
    public event KeyEventHandler KeyUp;

谁能帮帮我,非常感谢!

【问题讨论】:

【参考方案1】:

鉴于您发布的代码和含糊的“我收到一条错误消息”(这不是一个实际问题,也不是一个有用的问题陈述......总是具体),您似乎没有引用System.Windows.Forms.dll。另一方面,如果您没有引用 Winforms 程序集,则不清楚为什么您在使用 KeyEventArgs 时也不会收到错误,因为这是在同一个程序集中定义的。

也就是说,假设您在使用 KeyEventHandler 时遇到的错误只是它没有定义,您可以定义相同的类型供您自己使用:

public delegate void KeyEventHandler(object sender, KeyEventArgs e);

即,只需从 the documentation 复制委托类型声明。

现在,所有 都说,如果您没有引用 Winforms 程序集,并且您收到 KeyEventArgs 类型的错误消息,正如预期的那样,您可能要考虑不复制此方法的 Winforms 实现,而只需使用您自己的事件处理程序声明您自己的事件 args 类型。您返回的唯一内容是虚拟键代码,因此您不妨为此定义自己的类型:

class KeyboardHookEventArgs : EventArgs

    public int VirtualKeyCode  get; 

    public KeyboardHookEventArgs(int virtualKeyCode)
    
        VirtualKeyCode = virtualKeyCode;
    

…然后是事件:

public event EventHandler<KeyboardHookEventArgs> KeyDown;
public event EventHandler<KeyboardHookEventArgs> KeyUp;

您在哪里创建像 new KeyboardHookEventArgs(kbStruct.VirtualKeyCode) 这样的 args 对象。

请注意,您的事件引发实现不是线程安全的。在 C# 中使用空条件运算符会更安全,也更惯用,例如:

if (wParam == (IntPtr)WM_KEYDOWN)

    KeyDown?.Invoke(this, new KeyboardHookEventArgs(kbStruct.VirtualKeyCode));

您还应该为sender 传递一个正确的值,即this,如上所示。如果您希望事件没有发送者,那么它(以及班级的其他成员)应该只是 static

【讨论】:

“我无法将键码写入控制台屏幕”——这听起来像是一个全新的问题。您提出的 这个 问题与缺少的类型有关。如果您在执行此操作时遇到其他问题,则需要将其作为一个或多个新问题发布。

以上是关于如何修复 C# 控制台应用程序中的错误 KeyEventHandler?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 C# MOngoDB 中的日期匹配错误

如何修复 CORS 错误:ASP .NET C# 中的 MethodDisallowedByPreflightResponse

如何修复 Angular 中的此错误并将数据输出到 PDF?

如何修复以下 C# 错误?

如何恢复信息或修复 c# 错误 cs0246? [复制]

如何在 C# 的线程中以编程方式复制 Excel 文件时修复访问拒绝错误