通过挂钩直接将击键发送到另一个进程

2024-01-17

我想知道,在摆弄了 SendInput、SendKeys、PostMessage、SendMessage、SendNotifyMessage、keybd_event 等各种问题之后。为了找到这一点......尝试将键盘输入发送到另一个非前台进程是非常挑剔和不可靠的。

我尝试了一种 SendInput 方法,其中我欺骗了 Z 顺序(以将当前窗口保持在顶部)并快速将第 3 方窗口置于前台,发送输入,然后重新将我的窗口置于前台。其中最终失败了,而且,不知何故,不知道为什么,在非前台的情况下也设法在我的窗口上进行击键(导致两个窗口之间发送和接收的无限循环,直到我设法关闭该进程)。

我尝试过 SendMessage 和 PostMessage 的不同组合。一种用于向下,一种用于向上,因为同时使用向下和向上会导致问题,就像两者都使用 PostMessage 一样,导致密钥在接收窗口上重复。或 SendMessage 两者,这会导致文本输入问题,但其他功能工作正常。用于 keydown 的 SendMessage 和用于 keyUp 的 PostMessage 适用于所有功能,但可靠性急剧下降,并且增加了按键事件的延迟。只有用于 keydown 的 PostMessage 和用于 keyup 的 SendMessage 的组合才能够做任何有用的事情,keyup 注册的失败率可能为 5-10%。 SentNotifyMessage 也是如此(就可靠性而言,其行为方式与 SendMessage 基本相同)。

所以本质上,我已经到了最后,我想知道如何直接将一个钩子注入目标窗口,并做一些巫术以这种方式向其发送击键,绕过消息队列等。这样做的方式将不处理全局按键事件,并且仅影响目标窗口。唯一的问题是我对注入/挂钩等方面一无所知。所以我向社区求助。

Wut do?


这是一段小代码,允许您向后台应用程序发送消息。例如,要发送“A”字符,只需调用 sendKeylines(Keys.A),并且不要忘记使用命名空间 System.windows.forms 以便能够使用 Keys 对象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace keybound
{
class WindowHook
{
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    public static void sendKeystroke(ushort k)
    {
        const uint WM_KEYDOWN = 0x100;
        const uint WM_SYSCOMMAND = 0x018;
        const uint SC_CLOSE = 0x053;

        IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");

        IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
        //IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
    }
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过挂钩直接将击键发送到另一个进程 的相关文章

随机推荐