views:

739

answers:

2

I am using the below code to disable the Alt+Tab, Alt+Esc, Ctrl+Esc, and Windows Key but somehow it is not working. Please help me rectify it.

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

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

        [DllImport("user32.dll", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi)]
        private static extern int SetWindowsHookEx(
           int idHook,
           LowLevelKeyboardProcDelegate lpfn,
           int hMod,
           int dwThreadId);

        [DllImport("user32.dll")]
        private static extern int UnhookWindowsHookEx(int hHook);

        [DllImport("user32.dll", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi)]
        private static extern int CallNextHookEx(
            int hHook, int nCode,
            int wParam, ref KBDLLHOOKSTRUCT lParam);

        const int WH_KEYBOARD_LL = 13;
        private int intLLKey;
        private KBDLLHOOKSTRUCT lParam;

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

        private int LowLevelKeyboardProc(
            int nCode, int wParam,
            ref KBDLLHOOKSTRUCT lParam)
        {
            bool blnEat = false;
            switch (wParam)
            {
                case 256:
                case 257:
                case 260:
                case 261:
                    //Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key
                    if (((lParam.vkCode == 9) && (lParam.flags == 32)) ||
                    ((lParam.vkCode == 27) && (lParam.flags == 32)) || ((lParam.vkCode ==
                    27) && (lParam.flags == 0)) || ((lParam.vkCode == 91) && (lParam.flags
                    == 1)) || ((lParam.vkCode == 92) && (lParam.flags == 1)) || ((true) &&
                    (lParam.flags == 32)))
                    {
                        blnEat = true;
                    }
                    break;
            }

            if (blnEat)
                return 1;
            else return CallNextHookEx(0, nCode, wParam, ref lParam);

        }

        private void KeyboardHook(object sender, EventArgs e)
        {
            intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL,new LowLevelKeyboardProcDelegate(LowLevelKeyboardProc),
                       System.Runtime.InteropServices.Marshal.GetHINSTANCE(
                       System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
        }

        private void ReleaseKeyboardHook()
        {
            intLLKey = UnhookWindowsHookEx(intLLKey);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
                KeyboardHook(this, e);
            else
                ReleaseKeyboardHook();
        }
    }
}
+2  A: 

The code in general is working just fine. The effect you are witnessing likely stems from running under the Visual Studio debugger, which usually implies you are running within the Visual Studio Hosting Process (vshost.exe).

This means that the call to System.Reflection.Assembly.GetExecutingAssembly() within your KeyboardHook() function is returning vshost.exe rather than your executable, consequently the desired effect of installing a hook for your executable can not be achieved.

So to see your code in effect you'll have to do one of the following:

  • run it outside of Visual Studio
  • run it inside Visual Studio, but via menu 'Debug'->'Start without Debugging'
  • disable the Visual Studio Hosting Process, see below

Note that you could disable the Visual Studio Hosting Process, but please be aware of the potential side effects, citation:

When the hosting process is disabled, several debugging features are unavailable or experience decreased performance. For more information, see Debugging and the Hosting Process.

Steffen Opel
A: 

You can check out my answer to a related question over here. Notice the difference in the RegisterLowLevelHook method (you called yours KeyboardHook so you know what to compare). I've not had any problems using this even when debugging from VS. Basically, as others have stated, don't use the GetExecutingAssembly method but instead what I have listed in the other answer.

Here is the excerpt for the one function of interest to you:

private IntPtr RegisterLowLevelHook(LowLevelKeyboardProc hook)
{
    IntPtr handle = IntPtr.Zero;

    using (Process currentProcess = Process.GetCurrentProcess())
    using (ProcessModule currentModule = currentProcess.MainModule)
    {
        IntPtr module = Kernel32.GetModuleHandle(currentModule.ModuleName);
        handle = User32.SetWindowsHookEx(HookType.KEYBOARD_LL, hook, module, 0);
    }

    return handle;
}
Erich Mirabal