LoginSignup
48
55

More than 5 years have passed since last update.

PowerShellでSendKeysを使ってみた

Last updated at Posted at 2016-12-17

経緯

仕事で使うメッセンジャーツールで毎回同じメンバーのグループを作る必要があるのですが、
そのツールが提供する設定やらコマンドやらでは、その操作を自動化できそうになかったので、
しょうがなく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)

48
55
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
55