Непосредственная отправка нажатий клавиш в другой процесс путем подключения

Мне интересно, после всех проблем с SendInput, SendKeys, PostMessage, SendMessage, SendNotifyMessage, keybd_event и т.д. и т.д. Чтобы найти это хорошо... попытка отправить ввод с клавиатуры в другой процесс без переднего плана довольно тонкая и ненадежная.

Я попробовал метод SendInput, где я обманываю Z-порядок (чтобы сохранить текущее окно сверху) и быстро вырезал окно третьей стороны, отправлял вход и повторно просматривал мое окно. Из-за чего, в конечном счете, не удалось, а также, как-то, не знаете, почему, удалось также процитировать нажатия клавиш на моем окне, а не на переднем плане (вызывая бесконечный цикл отправки и получения между двумя окнами, пока мне не удалось закрыть процесс).

Я пробовал разные комбинации SendMessage и PostMessage. Один для вниз, один для вверх, поскольку использование как для перехода вниз, так и вверх приводит к проблемам, например, с PostMessage для обоих, в результате чего ключ дублируется в окне приема. или SendMessage для обоих, что вызвало проблемы с вводом текста, но другие функции работали нормально. SendMessage для keydown и PostMessage для keyUp работал для всех функций, но уровень надежности резко снижался, а также добавлял задержку в ключевые события. Только комбинация PostMessage для keydown и SendMessage для keyup удалось сделать что-нибудь полезное, возможно, 5-10% отказов регистрации регистрации. То же самое касается SentNotifyMessage (ведет себя в основном так же, как SendMessage, насколько это касается надежности).

Итак, по сути, я нахожусь в конце, и я хотел знать о том, как напрямую вводить крючок в целевое окно, и делать некоторые вуду, чтобы посылать ему такие нажатия, обходя очередь сообщений и т.д. Сделав это в способ, который не будет обрабатывать события глобального ключа, и влияет только на целевое окно. Единственное, что я не знаю, когда дело доходит до инъекций/перехвата и т.д. Поэтому я обращаюсь к вам, сообществу.

Что делать?

Ответ 1

Это небольшой код, который позволяет вам отправлять сообщение в фоновое приложение. Чтобы отправить "A" char, например, просто вызовите sendKeystroke (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);
    }
}
}

Ответ 2

Возможно, вам придется обходиться с этим, но вы можете отправлять данные через процесс. Это может не сработать для вашей ситуации, но это мысль.

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

Если это не сработает, вы всегда можете:

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