gpt4 book ai didi

c# - 创建一个成功创建到单个应用程序的 WH_SHELL Hook 的 C# 项目

转载 作者:太空狗 更新时间:2023-10-29 19:44:04 28 4
gpt4 key购买 nike

我正在尝试创建一个可以检测任务栏图标何时闪烁的项目。您通常通过在应用程序中创建一个 Hook 并检查适当的消息来完成此操作。在这种情况下,可以通过在应用程序中创建 WH_SHELL Hook 、等待 HSHELL_REDRAW 消息并检查 lParam 变量是否为 TRUE 来检测消息。

根据文档,如果 lParam 值为真,则 wParam 变量中的窗口句柄所引用的窗口正在闪烁。太好了。

问题是我一辈子都弄不明白如何实际创建 WH_SHELL Hook 。创建钩子(Hook)的代码看起来相当简单:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

class Flashy {
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
protected static extern IntPtr SetWindowsHookEx(int code, HookProc func, IntPtr hInstance, int threadID);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

private int WH_SHELL = 10;
static IntPtr hHook;

public void doStuff() {
using (Process process = Process.GetCurrentProcess())
using (ProcessModule module = process.MainModule)
{
IntPtr hModule = GetModuleHandle(module.ModuleName);
MyDLL.Class1.hHook = SetWindowsHookEx(WH_SHELL, MyDLL.Class1.MyHookProc, hModule, 0);
}
}
}

现在,根据我的阅读,WH_SHELL 需要一个 dll。所以我的看起来像:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace FlashyDLL
{
public class Class1
{

//This is the Import for the CallNextHookEx function.
//Use this function to pass the hook information to the next hook procedure in chain.
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

public static IntPtr hHook;

public static int MyHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);

switch (nCode)
{
case 6: //HSHELL_REDRAW
break;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
}

那我做错了什么?谢谢!

*编辑:

这是有效的代码的最后一部分。它基本上是接受的答案中的代码,并添加了一些小的内容。我以这种方式发布它是因为我讨厌尝试将线程的各个部分的代码拼凑在一起,而且我认为其他人也这样做。

请注意,这是一个全局 shell Hook ,而不是特定于应用程序的 Hook ,因此您必须根据您要查找的句柄检查 lParam 句柄,以确保闪现消息与正确的窗口有关。

第 1 步:接收消息的窗口:

using System;
using System.Windows.Forms;

public class TestAlertForm : Form
{
private IntPtr myWindow;
private int uMsgNotify = 0;
readonly IntPtr HSHELL_FLASH = new IntPtr(0x8006);

protected override void WndProc(ref Message m)
{
if (m.Msg == uMsgNotify)
{
if (m.WParam == HSHELL_FLASH)
{
if (m.LParam == myWindow)
{
MessageBox.Show("FLASH!");
}
}
}
base.WndProc(ref m);
}
}

第 2 步:PInvokes:

public class Win32 {
[DllImport("user32.dll", EntryPoint = "RegisterWindowMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int RegisterWindowMessage(string lpString);

[DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int RegisterShellHookWindow(IntPtr hWnd);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);
}

第 3 步:激活 Hook :

var taf = new TestAlertForm();
myWindow = FindWindowByCaption(0, "My Window Title");
uMsgNotify = RegisterWindowMessage("SHELLHOOK");
Win32.RegisterShellHookWindow(taf.Handle);

最佳答案

好的,事实证明这在 .Net 中有点棘手——但这是可能的。可以使用SetWindowsHookEx通过ID直接 Hook 到单个线程,但这种方式更简单,更容易匹配到窗口。

警告:这依赖于内部 USER32.dll 调用。

第 1 步:接收消息的窗口:

using System;
using System.Windows.Forms;

public class TestAlertForm : Form
{
readonly IntPtr HSHELL_FLASH = new IntPtr(0x8006);

protected override void WndProc(ref Message m)
{
if (m.WParam == HSHELL_FLASH)
{
// TODO: DO WORK HERE
// m.LParam <-- A handle to the window that is 'flashing'
// You should be able to match this to your target.
MessageBox.Show("FLASH!");
}
base.WndProc(ref m);
}
}

第 2 步:PInvokes:

public class Win32 {
[DllImport("user32.dll")]
public static extern bool RegisterShellHookWindow(IntPtr handle);
}

第 3 步:激活 Hook :

var taf = new TestAlertForm();
Win32.RegisterShellHookWindow(taf.Handle);

之后,您应该会看到一个消息框,显示每次闪烁。这只是一个快速的技巧,我还没有对其进行太多测试。

祝你好运!

关于c# - 创建一个成功创建到单个应用程序的 WH_SHELL Hook 的 C# 项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22087105/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com