.NET 3.x Исключение при блоке клавиши Win - C#

Узнай цену своей работы

Формулировка задачи:

Вообщем понадобилось мне отключить клавишу Win (в разумных целях), так вот при нажатие первый раз блочит, при повторном, выдает исключение, и всё накрывается разом) Сам класс:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
 
internal class WinBlock
{
    [StructLayout(LayoutKind.Sequential)]
    private struct KBDLLHOOKSTRUCT
    {
        public Keys key;
        public int scanCode;
        public int flags;
        public int time;
        public IntPtr extra;
    }
 
    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool UnhookWindowsHookEx(IntPtr hook);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string name);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern short GetAsyncKeyState(Keys key);
 
    private IntPtr ptrHook;
    private LowLevelKeyboardProc objKeyboardProcess;
 
    private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
    {
        if (nCode >= 0)
        {
            KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
            if (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin)
            {
                return (IntPtr)1;
            }
        }
        return CallNextHookEx(ptrHook, nCode, wp, lp);
    }
    private delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, IntPtr lParam);
 
    public void SetHook()
    {
        ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
        objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
        ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
    }
    public void Unhook()
    {
        if (ptrHook != IntPtr.Zero)
        {
            UnhookWindowsHookEx(ptrHook);
            ptrHook = IntPtr.Zero;
        }
    }
}
Исключение:
Обнаружено событие CallbackOnCollectedDelegate
Message: Был произведен обратный вызов делегата типа "WinBlock+LowLevelKeyboardProc::Invoke", 
полученного сборщиком мусора. 
Это может привести к сбоям приложения, а также к повреждению или утрате данных. 
При передаче делегатов в неуправляемый код управляемое приложение 
должно поддерживать их существование,
 пока не будет гарантировано, что они больше никогда не будут вызваны.
Есть ли у кого нибудь рабочий пример: или же как бороться..?

Решение задачи: «.NET 3.x Исключение при блоке клавиши Win»

textual
Листинг программы
        private void button1_Click(object sender, EventArgs e)
        {
            WinBlock.SetHook();
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            WinBlock.Unhook();
        }
 
        internal static class WinBlock
        {
            [StructLayout(LayoutKind.Sequential)]
            private struct KBDLLHOOKSTRUCT
            {
                public Keys key;
                public int scanCode;
                public int flags;
                public int time;
                public IntPtr extra;
            }
 
            private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool UnhookWindowsHookEx(IntPtr hook);
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr GetModuleHandle(string name);
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern short GetAsyncKeyState(Keys key);
 
            private static IntPtr ptrHook;
 
            
            private static LowLevelKeyboardProc objKeyboardProcess;
 
            //тут зафиксируем на всякий случай
            private static GCHandle gcObjKeyboardProcess = GCHandle.Alloc(objKeyboardProcess);
 
            private static IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
            {
                if (nCode >= 0)
                {
                    KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
                    if (objKeyInfo.key == Keys.LWin || objKeyInfo.key == Keys.RWin)
                    {
                        return (IntPtr)1;
                    }
                }
                return CallNextHookEx(ptrHook, nCode, wp, lp);
            }
            
            //Зачем дважды объявил? 
            //private delegate IntPtr LowLevelKeyboardProcDelegate(int nCode, IntPtr wParam, IntPtr lParam);
 
            public static void SetHook()
            {
                ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
                objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
                ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
            }
            public static void Unhook()
            {
                if (ptrHook != IntPtr.Zero)
                {
                    UnhookWindowsHookEx(ptrHook);
                    ptrHook = IntPtr.Zero;
                }
            }
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4.125 из 5
Похожие ответы