.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;
}
}
}