The WH_GETMESSAGE hook type is not working in .NET 7
See original GitHub issueDescription
Hello!
The P/Invoked SetWindowsHookEx
method using the WH_GETMESSAGE hook type is not working in .NET 7. The messages that are constructed seem odd, for example in .NET 7 the WM_LBUTTONDOWN message is never created. The issue seems to be e regression as the same code and setup is working in .NET 6.
Reproduction Steps
- Create a simple WinForms project and target .NET 7.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
- In the click event of a button install the hook:
using System.Runtime.InteropServices;
namespace GetMessageHookNet7
{
public partial class Form1 : Form
{
const int WM_LBUTTONDOWN = 0x201;
private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(HookType code, HookProc func, IntPtr hInstance, int threadID);
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.button1.Enabled = false;
int threadId = GetCurrentThreadId();
SetWindowsHookEx(HookType.WH_GETMESSAGE, new HookProc(GetMessageHookProc), IntPtr.Zero, threadId);
}
private int GetMessageHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code >= 0 && (long)wParam > 0)
{
Message msg = (Message)Marshal.PtrToStructure(lParam, typeof(Message));
if (msg.Msg == WM_LBUTTONDOWN)
{
}
}
return 0;
}
private enum HookType
{
WH_MSGFILTER = -1,
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
}
}
- Put a breakpoint in the
GetMessageHookProc
inside the if statement where we check for theWM_LBUTTONDOWN
message. - Build and run the project.
- Click the button to install the hook.
- Click anywhere on the form.
- Notice that you will not stop at the breakpoint.
Debugging the project, you will notice that some very strange messages be generated. I am attaching the test project for reference. GetMessageHookNet7.zip
The issue also does not reproduce in .NET 6. I am attaching a short gif file showing the observed behavior.
Expected behavior
The breakpoint inside the GetMessageHookProc is hit.
Actual behavior
The breakpoint inside the GetMessageHookProc is not hit.
Regression?
Yes, this issue is a regression. It does not reproduce in .NET 6.
I tested it in the latest version of VS2022 - 17.4.0 Preview 5.0 and with .NET 7 SDK: 7.0.100-rc.2.22477.23 I also tested with the first preview of .NET 7 - 7.0.100-preview.1.22110.4 and issue still reproduces.
Known Workarounds
No response
Configuration
No response
Other information
No response
Issue Analytics
- State:
- Created a year ago
- Comments:13 (12 by maintainers)
Top GitHub Comments
@dreddy-work, @RussKie Please do not put this in “known issues”. This is an unsafe use of undocumented internals. Nobody should be doing this as we could break people worse in the future by adding additional functionality in
Message
(if we added additional fields this sort of hard blit could AV). While we were able to make an accommodation in this case, I don’t want to give any inclination that this sort of thing (relying on internals) is ok or something that we can / will fix. If we find the impact is widespread then we can reconsider adding to “known issues” with the appropriate warning flags.#8063 fixes this for .NET 8.
We’ve made a number of internal changes to the
Message
struct to harden our code against casting mistakes. The internal layout changed in the process of doing this.