Help us understand the problem. What is going on with this article?

PowerShellでSendKeysを使ってみた

More than 1 year has passed since last update.

経緯

仕事で使うメッセンジャーツールで毎回同じメンバーのグループを作る必要があるのですが、
そのツールが提供する設定やらコマンドやらでは、その操作を自動化できそうになかったので、
しょうがなくSendKeys操作でやることにしました。
せっかくの機会なので、こういう場面で自動化しやすくするためにPowerShellの関数を作り、
その過程で得た知識の備忘録として記載。

SendKeysとは

・キーストローク(打鍵、キーを押すこと)によってキーに対応した情報をアプリに送ること。
 また、キーストローク単体でSendKeysと同じ意味で使われることもある。
・自動化するにあたっての最終手段です。(妥協策)

メリット

・Windowsの標準ツールで実装、および、利用することができる。
(.NETやWSHの環境で動作できるため。他はよく知りません...)
・他のアプリのCUIコマンドやAPIを覚える必要がないので、学習コストが少ない。

デメリット

・SendKeysによる処理が実行中の間は他の操作ができない。
(フォーカスが変更されるので意図しない結果になってしまう)

キーの表記方法

キー コードのサンプル ※()内は補足説明
英数字記号 "a", "123", "!", " "(Space)
アクション "{BS}", "{DEL}", "~"(Enter), "{LEFT}"(左矢印), "{F4}"
制御 "^"(Ctrlキー), "+"(Shiftキー), "%"(Altキー) ※1
エスケープ "{^}"(^), "{{}{}}"({})
複数指定 "^(ac)"(Ctrl+Aで全選択したのちCtrl+Cでコピー)
ループ "{a 5}"(aaaaa) ※2

※1 日本特有のキー(半角/全角、変換)やWindowsロゴキー、アプリケーションキーは利用できない。
※2 1つのキーに対して指定できる。
コードの一覧についてはこちらのドキュメントを参照してください。
SendKeys メソッド

実装における注意点

・フォーカス(SendKeys操作の対象)
 普段、キーで操作しているときと同様、前面に操作したいアプリを配置すること。
 →自動化処理のはじめにアプリを起動するか、もしくは、すでに起動中のアプリを前面にする。
・Wait
 →アプリがキーストロークして反応できる状態まで待つ必要がある。
 →ウィンドウのフォーカスだけではなく、ウィンドウ内のどこにフォーカスがくるのかも気にすること。
 →マシンの性能によっては、Wait時間を調整する必要が出てくる。
・その他
 →ショートカットキーについては事前に知っておくこと。

PowerShellでの実装

動作環境
・Windows10
・PowerShell 5.1

Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms

<#
.Synopsis
   実行中の任意のプロセスにキーストロークを送る操作をします。
.DESCRIPTION
   パラメータのキーストローク、プロセス名がそれぞれ未指定の場合、何も実行されません。
   キーストロークのみが指定された場合は実行時のフォーカスへキーストロークを送り、
   プロセス名のみが指定された場合はフォーカスのみが指定されたプロセスに変更します。
.EXAMPLE
   Send-Keys -KeyStroke "test.%~" -ProcessName "LINE"

   このコマンドは既に起動中のLINEアプリに対して"test."と入力し、
   Altキーを押しながらEnterキーを押下する操作をしています。
#>
function Send-Keys
{
    [CmdletBinding()]
    [Alias("sdky")]
    Param
    (
        # キーストローク
        # アプリケーションに送りたいキーストローク内容を指定します。
        # キーストロークの記述方法は下記のWebページを参照。
        # https://msdn.microsoft.com/ja-jp/library/cc364423.aspx
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [string]
        $KeyStroke,

        # プロセス名
        # キーストロークを送りたいアプリケーションのプロセス名を指定します。
        # 複数ある場合は、PIDが一番低いプロセスを対象とする。
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true)]
        [string]
        $ProcessName,

        # 待機時間
        # コマンドを実行する前の待機時間をミリ秒単位で指定します。
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true)]
        [int]
        $Wait = 0
    )

    Process
    {
        $Process = ps | ? {$_.Name -eq $ProcessName} | sort -Property CPU -Descending | select -First 1
        Write-Verbose $Process", KeyStroke = "$KeyStroke", Wait = "$Wait" ms."
        sleep -Milliseconds $Wait
        if ($Process -ne $null)
        {
            [Microsoft.VisualBasic.Interaction]::AppActivate($Process.ID)
        }
        [System.Windows.Forms.SendKeys]::SendWait($KeyStroke)
    }
}

備考

Tabキーや方向キーを何回も連続で押す必要が出てきたら、以下のようなコードでスッキリと書けます。

# Before
Send-Keys "{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}test." -ProcessName "LINE"
# After
Send-Keys "$("{DOWN}" * 5)test." -ProcessName "LINE"

参考

Microsoft Developer Network|Windows Script Host
SendKeys メソッド
Windows管理者のためのWindows Script Host入門
第5回 WshShellオブジェクトの詳細(1) (4/4)

nimzo6689
東京でJavaEEを扱う5年目エンジニアです。
https://github.com/nimzo6689/
jcsc
「未知なる可能性への挑戦」がモットー。愛媛生まれのエンジニア集団。
https://www.jcsc.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした