Skip to content

The WH_GETMESSAGE hook type is not working in .NET 7 #8062

@icom85

Description

@icom85

Description

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

  1. 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>
  1. 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
        }
    }
}
  1. Put a breakpoint in the GetMessageHookProc inside the if statement where we check for the WM_LBUTTONDOWN message.
  2. Build and run the project.
  3. Click the button to install the hook.
  4. Click anywhere on the form.
  5. 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.
net7-hook

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions