c# winapi c#-4.0 code-injection sendmessage

c# - Directamente enviando pulsaciones de teclas a otro proceso mediante el enganche



winapi c#-4.0 (2)

Este es un pequeño código que le permite enviar mensajes a una aplicación de fondo. Para enviar el carácter "A", por ejemplo, simplemente llame a sendKeystroke (Keys.A), y no se olvide de usar el espacio de nombres System.windows.forms para poder usar el objeto 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); } } }

Me pregunto, después de jugar con todo tipo de problemas con SendInput, SendKeys, PostMessage, SendMessage, SendNotifyMessage, keybd_event, etc. y así sucesivamente. Encontrarlo bien ... intentar enviar una entrada de teclado a otro proceso que no sea de primer plano es bastante quisquilloso y poco confiable.

Probé un método de SendInput en el que truco el orden Z (para mantener la ventana actual en la parte superior) y rápidamente en primer plano la ventana de terceros, envío la entrada y vuelvo a poner en primer plano mi ventana. De los cuales fallaron, y también, de alguna manera, no estoy seguro por qué, también pude procesar las teclas en mi ventana mientras no estaba en primer plano (causando un ciclo infinito de envío y recepción entre dos ventanas hasta que logré cerrar el proceso).

Probé diferentes combinaciones de SendMessage y PostMessage. Uno para abajo, uno para arriba, ya que usar tanto para abajo como para arriba genera problemas, como con PostMessage para ambos, haciendo que la llave se duplique en la ventana de recepción. o SendMessage para ambos, lo que causó problemas con el ingreso de texto, pero otras funciones funcionaron bien. SendMessage para keydown y PostMessage para keyUp funcionaron para todas las funciones, pero la tasa de confiabilidad disminuyó drásticamente, así como también agregó latencia en eventos clave. Solo una combinación de PostMessage para keydown y SendMessage para keyup logró hacer algo útil, con una tasa de fallas de 5-10% en el registro de keyup. Lo mismo ocurre con SentNotifyMessage (se comporta básicamente de la misma manera que SendMessage en lo que respecta a la fiabilidad).

Así que esencialmente, estoy en el final, y quería saber cómo inyectar directamente un gancho en la ventana de destino, y hacer algo de vudú para enviar las pulsaciones de teclado de esa manera, pasando por alto la cola de mensajes, etc. Haciéndolo de una manera que lo hará no procesa eventos clave globales, y solo afecta la ventana de destino. Lo único es que soy bastante desconocido cuando se trata de inyectar / enganchar, etc. Así que me dirijo a ti, comunidad.

¿Wut do?


Es posible que tenga que perder el tiempo con esto, pero puede enviar datos por proceso. Esto puede no funcionar para su situación, pero es un pensamiento.

using System; using System.Runtime.InteropServices; using System.Diagnostics; [DllImport("user32.dll", EntryPoint = "FindWindowEx")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("User32.dll")] public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam); static void Send(string message) { Process[] notepads = Process.GetProcessesByName("notepad"); if (notepads.Length == 0) return; if (notepads[0] != null) { IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null); SendMessage(child, 0x000C, 0, message); } }

Si eso no funciona, siempre puedes hacerlo:

System.Threading.Thread.Sleep(1000); //User clicks on active form. System.Windows.Forms.Sendkeys.Sendwait("<Message>");