我不能用C#禁用Windows Key

use*_*575 1 c# pinvoke winapi keyboard-hook

我使用的是Windows 8.我尝试使用c#禁用Windows Key,例如http://tamas.io/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/.它没有错误,但Windows键未被禁用.如何用C#禁用Windows Key?

这是我的代码.

namespace TestDisable
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("user32", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hMod, int dwThreadId);
        [DllImport("user32", EntryPoint = "UnhookWindowsHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int UnhookWindowsHookEx(int hHook);
        public delegate int LowLevelKeyboardProcDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
        [DllImport("user32", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int CallNextHookEx(int hHook, int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
        public const int WH_KEYBOARD_LL = 13;

        /*code needed to disable start menu*/
        [DllImport("user32.dll")]
        private static extern int FindWindow(string className, string windowText);
        [DllImport("user32.dll")]
        private static extern int ShowWindow(int hwnd, int command);

        private const int SW_HIDE = 0;
        private const int SW_SHOW = 1;

        public struct KBDLLHOOKSTRUCT
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        public static int intLLKey;

        public int LowLevelKeyboardProc(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)
        {
            bool blnEat = false;

                       try
        {
            switch (wParam)
            {
                case 256:
                case 257:
                case 260:
                case 261:

                    //Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
                    blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32))  // alt+tab
                        | ((lParam.vkCode == 27) && (lParam.flags == 32)) // alt+esc
                        | ((lParam.vkCode == 27) && (lParam.flags == 0))  // ctrl+esc
                        | ((lParam.vkCode == 91) && (lParam.flags == 1))  // left winkey
                        | ((lParam.vkCode == 92) && (lParam.flags == 1))
                        | ((lParam.vkCode == 73) && (lParam.flags == 0));

                    break;
            }


        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

            if (blnEat == true)
            {
                return 1;
            }
            else
            {
                return CallNextHookEx(0, nCode, wParam, ref lParam);
            }
        }

         private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
        intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 8

您没有执行任何错误检查.在编辑中,您添加代码以捕获Win32函数引发的异常.但Win32函数不会引发异常.相反,他们通过返回值来传达成功与失败.

在这种情况下intLLKey返回为0.这表明失败.挂钩未设置.让我们添加一些错误检查:

intLLKey = SetWindowsHookEx(...);
if (intLLKey == 0)
    throw new Win32Exception();
Run Code Online (Sandbox Code Playgroud)

现在,您将看到文本引发的异常:

指定的模块无法找到.

这是ERROR_MOD_NOT_FOUND.大概是因为你提供的模块句柄不被识别为与你传递的钩子proc函数指针相关联.这是托管程序集的常见问题,其中interop委托是在运行时动态创建的.

这是一种可能的解决方案.首先,修复你的p/invoke声明:

public delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hHook);

[DllImport("user32", EntryPoint = "CallNextHookEx", SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
Run Code Online (Sandbox Code Playgroud)

然后获取模块句柄并调用SetWindowsHookEx如下:

using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
{
    intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(curModule.ModuleName), 0);
}
if (intLLKey.ToInt64() == 0)
{
    throw new Win32Exception();
}
Run Code Online (Sandbox Code Playgroud)

由于我所做的所有类型更改,您还必须修复大量编译错误,主要与使用IntPtr指针大小的句柄值有关.就是这样HHOOK.intLLKey你打电话时也必须通过CallNextHookEx.通过这些更改,您的代码会挂钩键盘事件.这些方面的东西:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

    [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("user32", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
    public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
    public static extern bool UnhookWindowsHookEx(IntPtr hHook);

    [DllImport("user32", EntryPoint = "CallNextHookEx", SetLastError = true)]
    public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);

    public const int WH_KEYBOARD_LL = 13;

    /*code needed to disable start menu*/
    [DllImport("user32.dll")]
    private static extern int FindWindow(string className, string windowText);
    [DllImport("user32.dll")]
    private static extern int ShowWindow(int hwnd, int command);

    private const int SW_HIDE = 0;
    private const int SW_SHOW = 1;

    public struct KBDLLHOOKSTRUCT
    {
        public int vkCode;
        public int scanCode;
        public int flags;
        public int time;
        public int dwExtraInfo;
    }

    public static IntPtr intLLKey;

    public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
    {
        bool blnEat = false;

        try
        {
            switch (wParam.ToInt64())
            {
                case 256:
                case 257:
                case 260:
                case 261:

                    //Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
                    blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32))  // alt+tab
                        | ((lParam.vkCode == 27) && (lParam.flags == 32)) // alt+esc
                        | ((lParam.vkCode == 27) && (lParam.flags == 0))  // ctrl+esc
                        | ((lParam.vkCode == 91) && (lParam.flags == 1))  // left winkey
                        | ((lParam.vkCode == 92) && (lParam.flags == 1))
                        | ((lParam.vkCode == 73) && (lParam.flags == 0));

                    break;
            }


        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

        if (blnEat == true)
        {
            return (IntPtr)1;
        }
        else
        {
            return CallNextHookEx(intLLKey, nCode, wParam, ref lParam);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
        {
            intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(curModule.ModuleName), 0);
        }
        if (intLLKey.ToInt64() == 0)
        {
            throw new Win32Exception();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

故事的道德启示?检查错误.