21

SendInput、SendKeys、PostMessage、SendMessage、SendNotifyMessage、keybd_eventなどのあらゆる種類の問題をいじった後、私は疑問に思っています。それをうまく見つけるには...キーボード入力を別の非フォアグラウンドプロセスに送信しようとするのは、非常に面倒で信頼性がありません。

Zオーダーをだまして(現在のウィンドウを一番上に保つため)SendInputの方法を試し、サードパーティのウィンドウをすばやく前面に出し、入力を送信し、ウィンドウを再度前面に出しました。これは最終的に失敗し、また、どういうわけか、フォアグラウンドではなく、ウィンドウでもキーストロークを処理することができました (プロセスを閉じることができるまで、2 つのウィンドウ間で送受信の無限ループが発生します)。

SendMessage と PostMessage のさまざまな組み合わせを試しました。1 つはダウン用、もう 1 つはアップ用です。ダウンとアップの両方を使用すると問題が発生するためです。たとえば、PostMessage を両方に使用すると、受信ウィンドウでキーが重複します。または SendMessage の両方で、テキスト入力に問題が発生しましたが、他の機能は正常に機能しました。keydown の SendMessage と keyUp の PostMessage はすべての関数で機能しましたが、信頼性が大幅に低下し、キー イベントにレイテンシが追加されました。keydown 用の PostMessage と keyup 用の SendMessage の組み合わせのみが、何らかの有用な処理を行うことができ、keyup 登録の失敗率はおそらく 5 ~ 10% でした。同じことが SentNotifyMessage にも当てはまります (信頼性に関する限り、SendMessage と基本的に同じように動作します)。

つまり、本質的に、私は終わりに近づいており、フックをターゲットウィンドウに直接挿入し、ブードゥーを実行してキーストロークをそのように送信し、メッセージキューなどをバイパスすることについて知りたかったのです。グローバル キー イベントを発生させず、ターゲット ウィンドウにのみ影響します。唯一のことは、インジェクション/フッキングなどに関しては、私はかなり知識がないということです。だから、コミュニティの皆さんに頼ります。

どーする?

4

2 に答える 2

16

これは、バックグラウンド アプリケーションにメッセージを送信できるようにする小さなコードです。たとえば、「A」文字を送信するには、sendKeystroke(Keys.A) を呼び出すだけです。Keys オブジェクトを使用できるように、名前空間 System.windows.forms を使用することを忘れないでください。

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);
    }
}
}
于 2012-09-29T11:36:42.113 に答える
9

これをいじる必要があるかもしれませんが、プロセスを介してデータを送信できます。これはあなたの状況ではうまくいかないかもしれませんが、それは考えです。

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>");
于 2012-05-24T04:18:18.587 に答える