question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The WH_GETMESSAGE hook type is not working in .NET 7

See original GitHub issue

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

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:13 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
JeremyKuhnecommented, Oct 31, 2022

@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.

1reaction
JeremyKuhnecommented, Oct 28, 2022

#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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SetWindowsHookEx in C# - Stack Overflow
I'm trying to hook a 3rd party app so that I can draw to its screen. Drawing to the screen is easy, and...
Read more >
Breaking changes in .NET 7
Changes are grouped by technology area, such as ASP.NET Core or Windows Forms. This article indicates whether each breaking change is binary ...
Read more >
ASP.NET Core updates in .NET 7 Release Candidate 1
NET 7 Release Candidate 1 (RC1) is now available and includes many great new improvements to ASP.NET Core. Here's a summary of what's...
Read more >
Adding validation to strongly typed configuration objects in ...
In this post I describe how to to verify your strongly typed configuration objects are correctly bound to your configuration at app startup....
Read more >
.NET core vs .NET framework
Wondering about the difference between .NET Core & .NET Framework? Here's a quick guide on how to pick the right runtime environment for...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found