且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

通过直接挂钩发送击键到其他进程

更新时间:2023-11-30 17:11:22

这是一个小code,使您可以发送短信到后台运行的应用程序。要发送例如A字符,只需调用sendKeystroke(Keys.A),不要忘了使用空间System.Windows.Forms的是能够使用键对象。

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Runtime.InteropServices;
使用System.Windows.Forms的;命名空间keybound
{
类WindowHook
{
    函数[DllImport(user32.dll中)]
    公共静态外部的IntPtr FindWindow函数(字符串lpClassName,串lpWindowName);
    函数[DllImport(user32.dll中)]
    公共静态外部的IntPtr SendMessage函数(IntPtr的的HWND,UINT消息,IntPtr的的wParam,lParam的IntPtr的);
    函数[DllImport(user32.dll中)]
    公共静态外部的IntPtr PostMessage的(IntPtr的的HWND,UINT消息,IntPtr的的wParam,lParam的IntPtr的);    公共静态无效sendKeystroke(USHORT K)
    {
        常量UINT WM_KEYDOWN = 0x100的;
        常量UINT WM_SYSCOMMAND =量0x018;
        常量UINT SC_CLOSE = 0x053;        IntPtr的WindowToFind = FindWindow函数(NULL,未命名 - 记事本++);        IntPtr的result3 = SendMessage函数(WindowToFind,WM_KEYDOWN,((IntPtr的)K),(IntPtr的),0);
        // IntPtr的result3 = SendMessage函数(WindowToFind,WM_KEYUP,((IntPtr的)C),(IntPtr的),0);
    }
}
}

I'm wondering, after fiddling with all sorts of issues with SendInput, SendKeys, PostMessage, SendMessage, SendNotifyMessage, keybd_event, etc and so forth. To find that well... trying to send a keyboard input to another non-foreground process is quite finicky and unreliable.

I tried a method of SendInput where I trick the Z-order (to keep the current window on top) and quickly foreground the 3rd party window, send the input, and re-foreground my window. Of which ultimately failed, and also, somehow, not sure why, managed to also proc the keystrokes on my window as well while not foreground (causing an infinite loop of sending and receiving between two windows until I managed to close the process).

I've tried different combinations of SendMessage and PostMessage. One for down, one for up, as using both for down and up leads to issues, like with PostMessage for both, causing the key to duplicate on the receiving window. or SendMessage for both, which caused issues with text entry, but other functions worked ok. SendMessage for keydown and PostMessage for keyUp worked for all functions, but the reliability rate dropped dramatically, as well as adding latency into key events. Only a combination of PostMessage for keydown, and SendMessage for keyup managed to do anything useful, with a maybe 5-10% fail rate of keyup registering. Same goes for SentNotifyMessage (behaves basically in the same fashion as SendMessage as far as reliability goes).

So essentially, I'm at whit's end, and I wanted to know about directly injecting a hook into the target window, and doing some voodoo to send keystrokes to it that way, bypassing the message queue etc. Doing so in a way that will not proc global key events, and only affect the target window. Only thing is I'm pretty unknowledgeable when it comes to injecting/hooking, etc. So I turn to you, community.

Wut do?

This is a little code that allows you to send message to a backgrounded application. To send the "A" char for example, simply call sendKeystroke(Keys.A), and don't forget to use namespace System.windows.forms to be able to use the Keys object.

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);
    }
}
}