SetWindowsHookEx in C#
SetWindowsHookEx specifies the last two parameters thusly:
hMod
[in] Handle to the DLL containing the
hook procedure pointed to by the lpfn
parameter. The hMod parameter must be
set to NULL if the dwThreadId
parameter specifies a thread created
by the current process and if the hook
procedure is within the code
associated with the current process.
dwThreadId
[in] Specifies the identifier of the
thread with which the hook procedure
is to be associated. If this parameter
is zero, the hook procedure is
associated with all existing threads
running in the same desktop as the
calling thread.
I'm not sure you can use a .NET dll in the manner required, but you can certainly try.
Grab hMod
via Marshal.GetHINSTANCE(typeof(Form1).Module) and dwThreadId
via Process.Threads. Alternatively, set dwThreadId
to 0 if you want a global hook (ie. a hook for all GetMessage()
calls in the current desktop) but beware of the performance penalties.
SetWindowsHookEx does not work in C# .net core?
Low-level Windows hooks internally use Windows messaging. The thread that calls SetWindowsHookEx
must have the message loop in the end, which allows to call HookCallback
function. In C++ message loop looks like this:
MSG msg;
BOOL result;
for (;;)
{
result = GetMessage(&msg, nullptr, 0, 0);
if (result <= 0)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Find all required PInvoke definitions for GetMessage
, TranslateMessage
, DispatchMessage
and MSG
, translate this code to C# and place it instead of your endless loop while(true)
. You can find all this stuff at PInvoke.Net, see also this Microsoft forum discussion:
Console keyboard hook not getting called
https://social.msdn.microsoft.com/Forums/vstudio/en-US/ed5be22c-cef8-4615-a625-d05caf113afc/console-keyboard-hook-not-getting-called?forum=csharpgeneral
setting mouse hooks in C# with setwindowshookex: wparam and lparam always return constant
According to MSDN your lParam
is a pointer to MOUSEHOOKSTRUCT which can be easily converted from pointer to structure using this technique.
Working code would look like this:
[StructLayout(LayoutKind.Sequential)]
struct Point
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEHOOKSTRUCT
{
public Point pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
private int HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
// Do something.
var mhs = Marshal.PtrToStructure<MOUSEHOOKSTRUCT>(lParam);
Console.WriteLine($"point: {mhs.pt.X} {mhs.pt.Y}");
}
return CallNextHookEx(this.hookID, nCode, wParam, lParam);
}
SetWindowsHookEx is always returning zero in C#
Did you look at this page: https://support.microsoft.com/en-us/help/318804/how-to-set-a-windows-hook-in-visual-c--net ?
Your Dllimports are subtly different
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
vs
[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
SetWindowsHookEx another process made by C# always return 0 IntPtr
You cannot use a global WH_MOUSE
hook from C#, or indeed a thread specific WH_MOUSE
hook for a thread in a different process. That requires an unmanaged DLL.
From managed code you need to use WH_MOUSE_LL
, the low-level mouse hook. If you really need WH_MOUSE
then you will need to write the hook in native code so that the DLL can be injected into the target process.
SetWindowsHookEx seems not working for me in C# (WH_KEYBOARD_LL, global)
Is this a console app as Main(string[] args) and Console.ReadLine() would suggest?
if so then this might be the source of your problem
Related Topics
Are Ienumerable Linq Methods Thread-Safe
How to Secure Passwords Stored Inside Web.Config
How to Get the Colour of a Pixel at X,Y Using C#
How Can a Windows Service Determine Its Servicename
Merge 2 Datatables and Store in a New One
Why C# Won't Allow Field Initializer with Non-Static Fields
System.Io.File.Create Locking a File
How to Generically Format a Boolean to a Yes/No String
How to Implement a Navigation Button in Shared Application Resources
How to Put Conditional Required Attribute into Class Property to Work with Web API
C# - Making All Derived Classes Call the Base Class Constructor
C# Image.Clone Out of Memory Exception
Why Is List When Passed Without Ref to a Function Acting Like Passed with Ref
With Rx, How to Ignore All-Except-The-Latest Value When My Subscribe Method Is Running