web-dev-qa-db-fra.com

Envoi direct de touches à un autre processus via le raccordement

Je me demande, après avoir tripoté toutes sortes de problèmes avec SendInput, SendKeys, PostMessage, SendMessage, SendNotifyMessage, keybd_event, etc., etc. Pour trouver cela bien ... essayer d'envoyer une entrée de clavier à un autre processus non au premier plan est assez capricieux et peu fiable.

J'ai essayé une méthode de SendInput où je tromper l'ordre Z (pour garder la fenêtre actuelle en haut) et rapidement au premier plan la fenêtre tierce, envoyer l'entrée et recréer au premier plan ma fenêtre. Dont finalement échoué, et aussi, d'une manière ou d'une autre, je ne sais pas pourquoi, a également réussi à déclencher les frappes sur ma fenêtre sans être au premier plan (provoquant une boucle infinie d'envoi et de réception entre deux fenêtres jusqu'à ce que je réussisse à fermer le processus).

J'ai essayé différentes combinaisons de SendMessage et PostMessage. Un pour le bas, un pour le haut, car l'utilisation des deux pour le bas et le haut entraîne des problèmes, comme avec PostMessage pour les deux, provoquant la duplication de la clé sur la fenêtre de réception. ou SendMessage pour les deux, ce qui a causé des problèmes avec la saisie de texte, mais d'autres fonctions ont bien fonctionné. SendMessage pour keydown et PostMessage pour keyUp ont fonctionné pour toutes les fonctions, mais le taux de fiabilité a chuté de façon spectaculaire, tout en ajoutant de la latence aux événements clés. Seule une combinaison de PostMessage pour keydown et SendMessage pour keyup a réussi à faire quelque chose d'utile, avec un taux d'échec d'enregistrement de keyup peut-être de 5 à 10%. Il en va de même pour SentNotifyMessage (se comporte essentiellement de la même manière que SendMessage en ce qui concerne la fiabilité).

Donc, essentiellement, je suis à bout de souffle, et je voulais savoir comment injecter directement un crochet dans la fenêtre cible, et faire du vaudou pour lui envoyer des touches de cette façon, en contournant la file d'attente de messages, etc. ne déclenche pas les événements de clé globale et affecte uniquement la fenêtre cible. La seule chose est que je ne sais pas très bien quand il s'agit d'injecter/accrocher, etc. Je me tourne donc vers vous, communauté.

Que faire?

19
Hydra

Il s'agit d'un petit code qui vous permet d'envoyer un message à une application en arrière-plan. Pour envoyer le caractère "A" par exemple, il suffit d'appeler sendKeystroke (Keys.A), et n'oubliez pas d'utiliser l'espace de noms System.windows.forms pour pouvoir utiliser l'objet 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);
    }
}
}
16
Louisbob

Vous devrez peut-être jouer avec cela, mais vous pouvez envoyer des données via le processus. Cela peut ne pas fonctionner pour votre situation, mais c'est une pensée.

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 cela ne fonctionne pas, vous pouvez toujours faire:

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