たれながし.info

とあるITエンジニアの備忘録

PowerShellでマウス操作「任意の場所をクリック」

PowerShellでマウスカーソルを動かして、任意の場所をクリックする方法を紹介します。


はじめに

PowerShellでマウスを操作してクリックしたい!」と思い検索したところ、
「Stack Overflow(プログラミングに関する英語の掲示板)」で見つけることが出来たので実施してみます。

<参考>
stackoverflow.com

クリックする座標の確認

まず、クリックする地点の画面上の座標を確認する必要があります。

Windowsの座標系は、メインディスプレイの左上が原点(0, 0)、右がx軸、下がy軸の進行方向になります。
通常は座標は0以上の値となりますが、画面外やマルチディスプレイの場合はマイナスになることもあります。

座標はPowerShellを用いて確認可能です。

1. PowerShellスクリプトを実行し、3秒以内にクリックしたい場所にマウスカーソルを合わせる

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

Start-Sleep -s 3

$X = [System.Windows.Forms.Cursor]::Position.X
$Y = [System.Windows.Forms.Cursor]::Position.Y

Write-Output "X: $X | Y: $Y"
Read-Host

2. 座標が取得できる(画像では、x=714, y=318)

座標をクリックする

次に取得した座標の場所をクリックするPowerShellスクリプトです。

1. PowerShellスクリプトを実行する

# 座標
$x = 1000
$y = 800

# .NET Frameworkの宣言
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

# Windows APIの宣言
$signature=@'
[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@
$SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru

Start-Sleep -s 1

# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);
$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

動作解説

上記のPowerShellの動作を解説します。

まず、$x, $yにクリックする座標を指定します。
「# .NET Frameworkの宣言」「# Windows APIの宣言」の部分は、Windowsの機能を呼び出すために必要なものなので、取り合えず書いてください。

「[System.Windows.Forms.Cursor]::Position」に座標を代入することでマウスカーソルを移動します。
「$SendMouseClick::mouse_event」でマウスのクリックを実行します(イベントを発生させることでクリックしたことにする)。

左クリックは、Downイベントが0x0002、Upイベントが0x0004です。
右クリックは、Downイベントが0x0008、Upイベントが0x0010です。

Down/Upはセットで使います。
Downイベント→カーソル移動→Upイベントとすれば、ドラッグもできるはずです。

ダブルクリックはDown/Upを2回書きます。

$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);
$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);
$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

ホイールクリックなどのイベントも存在します。マイクロソフトの公式ドキュメントに説明があります。
mouse_event function (winuser.h) - Win32 apps | Microsoft Learn

関数化

カーソル移動とクリックの部分は関数化しても良いと思います。

PowerShellの関数は「関数名 $引数1 $引数2」という形で、引数をスペース区切りで渡します。
関数を呼び出す前に関数の定義が必要です。

function SingleClick_Right($x, $y){
    # マウスカーソル移動
    [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

    # クリックイベント生成
    $SendMouseClick::mouse_event(0x0008, 0, 0, 0, 0);
    $SendMouseClick::mouse_event(0x0010, 0, 0, 0, 0);
}

function DoubleClick_Left ($x, $y){
    # マウスカーソル移動
    [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

    # クリックイベント生成
    $SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);
    $SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);
    $SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);
    $SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);
}

# 関数呼び出し
SingleClick_Right $x $y
DoubleClick_Left $x $y

時間指定で実行

時間指定で実行したい場合はタスクスケジューラに登録してください。

コマンドで登録する場合

「schtasks」コマンドで登録します。

例)23:00に1度だけ、ps1ファイルを実行するタスク「MyTask」を作成する場合

> schtasks /create /tn "MyTask" /tr "powershell -ExecutionPolicy Bypass c:\Click-Position.ps1 " /sc once /st 23:00

> schtasks /query /tn "MyTask"

フォルダー\
タスク名                                 次回の実行時刻         状態
======================================== ====================== ===============
MyTask                                   2020/12/06 23:00:00    準備完了

<参考>
docs.microsoft.com

GUIで登録する場合

「タスクスケジューラ(taskschd.msc)」を起動して登録します。

<参考>
www.atmarkit.co.jp