C#でのウィンドウへのキー送信

結論としては、以下の2種類の方法があるとわかりました。

① .NetのSendKeys.SendWaitメソッド:
 → 最前面のウィンドウ限定。引数が単純で使いやすい。
② ・WindowsAPIのPostMessageメソッド:
 → 送信先のウィンドウ指定可能。引数が複雑で使いにくい。必要な引数はSpy++にて調査可能。

以下経緯などです。

今携わっている案件で、プログラムからキー送信を行うことで
外部のアプリをショートカットキーにより自動操作することになりました。

お客様の調査により、
.NetのSendKeys.SendWaitメソッドにより実現可能だとわかっていたのですが、
このメソッドは送信先を指定できず、必ず最前面のウィンドウにキー送信を行うもので、
自動操作中にユーザ操作などで最前面のウィンドウが切り替わってしまうと
誤ったアプリにキーを送信してしまうことになります。

そこで可能ならウィンドウを指定して送信するという方針になり、
社内メンバーからウィンドウのハンドルを引数に与えてキー送信できるメソッドがあると伺いました。

調べてみたところWindowsAPIのPostMessageがそれにあたるとわかり、
試してみたのですが、文字列を引数に与えるだけのSendKeys.SendWaitとは異なり、
引数が複雑(ハンドルとキー内容だけでなく、複数のパラメータを32bitに詰め込んだ値が必要)で、
目的のキーを送信するためにどうすればよいかわかりませんでした。

そこで更に調べてみたところ、VisualStudioに含まれるSpy++というアプリにより、
目的のソフトへキーを送信した際のメッセージをログ出力して、
送信時の引数を調べることができるとわかりました。
参考:
VBAのSendKeys,System.Windows.FormsのSendWaitなどが反応しないときに読む記事 – 適材適所

これにより、無事PostMessageによるキー送信をテストすることに成功しました。

結果的には、
操作対象のアプリはそもそも最前面に表示されている状態でないとキー送信による操作を受け付けないとわかったため、
今回はキー送信前に毎回ウィンドウのActivateする方針に決まりましたが、
PostMessage(+ Spy++による送信内容の調査)は今後何かしらに役に立ちそうだなと感じています。

また余談ですが、
調査中にPostMessageによりゲームにキー送信を行い自動で操作する旨の話をチラッと見かけました。
学生時代に見かけたゲームAIの研究で、
「ゲームの状態を画像処理で読み取り、行動を決定し、外部からゲームを操作するAI」
を見かけたことがあったのですが、
あの実現にはこの辺りのメソッドを呼んでいたのだなと懐かしみながら今更のように思いました。

以上です。

コメントを残す