This is the code for my keyhooking class, but it doesn't work. I was wondering if someone can tell me why? I'm instansiating it in another Console application. The debug message gives the proper output, but the keyboard hook simply doesn't catch keys. I was hoping if someone could tell me why.
namespace GlobalHooks
{
public class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static IntPtr _hookID = IntPtr.Zero;
private static String keysHooked = String.Empty;
private static LowLevelHookProc keyboardHook;
public delegate IntPtr LowLevelHookProc(int nCode, Int32 wParam, IntPtr lParam);
public delegate void KeyboardHandleFunction(int vkCode);
public static event KeyboardHandleFunction keyHookReturn;
public InterceptKeys(KeyboardHandleFunction func)
{
keyHookReturn = func;
keyboardHook = new LowLevelHookProc(HookCallback);
}
public static void debug()
{
Console.Write("\n[Success!] _hookID: "+_hookID);
Console.Write("\n[Success!] keyboardProc: "+keyboardHook.ToString());
}
private IntPtr SetupHook(LowLevelHookProc keyProcess)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, keyProcess,
GetModuleHandle(curModule.ModuleName), 0);
}
}
public void Hook()
{
_hookID = SetupHook(keyboardHook);
debug();
}
public void Unhook()
{
UnhookWindowsHookEx(_hookID);
}
public static void OnCallbackReturn(int nCode)
{
if (keyHookReturn != null)
{
keyHookReturn(nCode);
}
else
{
throw new Exception();
}
}
public static IntPtr HookCallback(int nCode, Int32 wParam, IntPtr lParam)
{
Console.WriteLine("Calledback"Wink;
if (nCode >= 0 && wParam == WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
OnCallbackReturn(nCode);
}
return CallNextHookEx((int)_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelHookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(int hhk, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
Are you calling Application.Run in your Main function?
The standard Console thread doesn't have a message loop, which is required for hooks to work properly, Application.Run takes care of that.
Related
I'm trying to disable specific keys when a specific process is detected, but for a reason, it's not set the hook correctly so it's not working.
The code should do:
Detect if notepad.exe has been detected (already coded the function but i didnt write it here).
Now from the checking thread, it will start the hook thread which will implement a low-level keyboard hook to prevent the user from using specific keys into the target process.
here is the code that I'm using:
[StructLayout(LayoutKind.Sequential)]
private struct KBDLLHOOKSTRUCT
{
public Keys key;
public int scanCode;
public int flags;
public int time;
public IntPtr extra;
}
//System level functions to be used for hook and unhook keyboard input
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);
//Declaring Global objects
private static IntPtr ptrHook;
private static LowLevelKeyboardProc objKeyboardProcess;
private const int WH_KEYBOARD_LL = 13;
private const int VK_CONTROL = 0x11;
public void Control()
{
MessageBox.Show("Control thread has been started");
ProcessModule objCurrentModule = Process.GetProcessesByName("notepad")[0].MainModule;
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
}
public static IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
{
if (nCode >= 0)
{
KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
MessageBox.Show("ncode >=0 !");
if (objKeyInfo.key == Keys.G || objKeyInfo.key == Keys.H || objKeyInfo.key == Keys.S) // Disabling Windows keys
{
MessageBox.Show("One of the specific keys has been detected!");
return (IntPtr)1;
}
}
return CallNextHookEx(ptrHook, nCode, wp, lp);
}
public static void Dispose()
{
UnhookWindowsHookEx(ptrHook);
}
public static void Hide()
{
ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule;
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);
}
public Form1()
{
InitializeComponent();
Thread cont = new Thread(Control);
cont.start();
}
I am running a global mouse hook from the main UI thread but wanted to run it in a background thread (comments appreciated), not sure how to achieve this. I am running some UIA code on background MTA thread but on updating the UI on the main thread the mouse becomes somewhat jerky when the user interface is being built for my application. I have tried cancelling all UIA event handlers in the application which were running on background MTA threads but still get the jerky mouse problem
Many thanks
MouseHook.MouseAction += new EventHandler(MouseHook_MouseAction);
MouseHook.Start();
private void MouseHook_MouseAction(object sender, EventArgs e)
{
//Do whatever
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace myApp
{
public static class MouseHook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
public static event EventHandler MouseAction = delegate { };
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
// WM_MOUSEMOVE = 0x0200,
//WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
public static void Start()
{
_hookID = SetHook(_proc);
}
public static void stop()
{
UnhookWindowsHookEx(_hookID);
}
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0);
if (hook == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
return hook;
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam || MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam ))
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
MouseAction(null, new EventArgs());
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
}
I want to get acquainted with WinAPI in C#.
I need to write a global mouse hook in the console application. I found the code that does this job. But I have a console application, and I shouldn't use Application.Run () from Windows.Forms.
I need to forward messages about the coordinates of the mouse from winAPI directly to the console window without winForms. How can i do this?
class InterceptMouse
{
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Add system.windows.forms as a reference to your project.
using System.Windows.Forms;
It should be work then.
I am working on a Project in c# and need to get Mouse Click Coordinates in the textbox. Clicking can be made outside the Screen. I have found a code in the internet but can't make the coordinates bring out in the textbox. Here is the code.. I was trying to write "hookStruct.pt.x" in HookCallBack but it didn't work as well. Does anyone have any idea how to do this?
namespace Mouse_Hook
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static LowLevelMouseProc _proc = HookCallback;
private const int WH_MOUSE_LL = 14;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
Console.Read();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private void Form1_Load(object sender, EventArgs e)
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
}
}
If I understand correctly, the best for your needs would be to put the hook functionality inside a static (global) class and expose a static event. In your case, the form will subscribe on that event when opened (and should unsubscribe when closed). Something like this
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Samples
{
public static class MouseHook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private const int WH_MOUSE_LL = 14;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private static IntPtr _hookID = IntPtr.Zero;
public static void Register()
{
if (_hookID != IntPtr.Zero) return;
_hookID = SetHook(HookCallback);
}
public static void Unregister()
{
if (_hookID == IntPtr.Zero) return;
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
var handler = LButtonDown;
if (handler != null) handler(null, EventArgs.Empty);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public static event EventHandler LButtonDown;
}
// Test
class TestForm : Form
{
Label label;
protected override void OnLoad(EventArgs e)
{
Controls.Add(label = new Label());
MouseHook.LButtonDown += OnHookLButtonDown;
base.OnLoad(e);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
MouseHook.LButtonDown -= OnHookLButtonDown;
}
private void OnHookLButtonDown(object sender, EventArgs e)
{
var pt = Control.MousePosition;
label.Text = "{" + pt.X + ", " + pt.Y + "}";
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MouseHook.Register();
try { Application.Run(new TestForm()); }
finally { MouseHook.Unregister(); }
}
}
}
Please note that this is just an example. A production code would extract the information from the hook parameters and expose a global events similar to the standard MoseMove, MouseDown etc.
I have a program that opens a GUI when run. I would then like to set up a mousehook using dllimports, but in order for it to work, I must call a new Application.Run() in this same class. Unfortunately though, this removes the original GUI. Is there any way I can run the mousehook on the original messageloop? I'm a bit lost here.
Here are a few key portions of the code:
//main
public static GUI GUIref;
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(GUIref = new GUI());
}
.
//Initializing constructor
public partial class GUI : Form
{
public GUI()
{
InitializeComponent();
keyReceive kR = new keyReceive();
mouseReceive mR = new mouseReceive();
}
}
.
//mousehook class:
public class mouseReceive : Form
{
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public mouseReceive()
{
_hookID = SetHook(_proc);
//***This is where I have been putting Application.Run() to make the mousehook work***
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
MessageBox.Show("");
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
In the mouseReceive constructor, you are setting the hook and then immediately unhooking it. If you insert the Application.Run() where your comment is, that blocks the thread until the new window closes, thus the hook is not unhooked and works. The real fix would be to remove UnhookWindowsHookEx(_hookID) from the constructor and put it into a IDisposable pattern.
Side note: You also might have problems if you try to instantiate more than one instance of your mouseReceive class as it has static members for _proc and _hookID.