2020年04月23日

「マウスふるふる」と同じ機能をPowerShellでも作れないかな?という試み

DIYプログラミングのお時間ですね。

リモートワークブームのおかげで、なぜだかSNS上で話題をよく見かけるようになったマウスふるふるなのですが、そもそもインターネットからファイルをダウンロードすることが許されないとか、許可されたexe以外を実行できない環境もあるとかで、ExcelだったかVBSだったかで同じような機能を作った、みたいな話も聞こえてきました。

となると、PowerShell版も作れるのかな?とふと思い浮かんで、試してみました。
50秒おきにマウスを左右に1ピクセルゆらす感じの。

# .NETのCursorクラスを利用するためにSystem.Windows.Formsをロード
add-type -AssemblyName System.Windows.Forms


while ($true) {

    # 50秒スリープ
    echo "50秒スリープ"
    Start-Sleep 50

    # 現在のマウスのX,Y座標を取得
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y
    echo "マウス座標:($x, $y)"

    # マウス座標を少し左にずらす
    $x++;
    [System.Windows.Forms.Cursor]::Position = new-object System.Drawing.Point($x, $y)
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y
    echo "→マウス座標:($x, $y)"

    # マウス座標を少し右にずらす
    $x--;
    [System.Windows.Forms.Cursor]::Position = new-object System.Drawing.Point($x, $y)
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y
    echo "→マウス座標:($x, $y)"
}



あれ?うまく動かない。スクリーン セーバーを1分に設定したら、60秒ちょっと経過したところでスクリーン セーバーが起動しちゃいました。
もしかして管理者権限で動かさないとダメとか…?とか思いましたが、管理者権限でもダメでした。

もしかして、もっとはっきり、かつ、時間をおいてマウスを動かさないとダメ?とか思いまして、1秒おいて10ピクセル右、また1秒おいて10ピクセル左、という動きを永久ループさせてみることにしました。


# .NETのCursorクラスを利用するためにSystem.Windows.Formsをロード
add-type -AssemblyName System.Windows.Forms


while ($true) {

    # 1秒スリープ
    echo "1秒スリープ"
    Start-Sleep 1

    # 現在のマウスのX,Y座標を取得
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y

    # マウス座標を少し左にずらす
    $x+=16;
    [System.Windows.Forms.Cursor]::Position = new-object System.Drawing.Point($x, $y)
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y
    echo "→マウス座標:($x, $y)"

    echo "1秒スリープ"
    Start-Sleep 1

    # マウス座標を少し右にずらす
    $x-=16;
    [System.Windows.Forms.Cursor]::Position = new-object System.Drawing.Point($x, $y)
    $x = [System.Windows.Forms.Cursor]::Position.X
    $y = [System.Windows.Forms.Cursor]::Position.Y
    echo "→マウス座標:($x, $y)"
}



やっぱりうまく動かない。スクリーン セーバーは動いてしまいました。
もしかすると、.NET Frameworkだとサンドボックス的なところの中で動くからうまく行かないとかでしょうか?よくわかりませんでした。

最初に触れた、ExcelだったかVBSだったかで同じような機能を作った方は、その後うまく動いたのかが気になりますね。
…と、ここまで書いて、ふと、マウスのポインタの移動ではダメで、マウスイベントを偽装させる必要があったことに気づきました。


というわけで、正しくはこう書きます。

# マウスふるふる(PowerShell版)   (C)2020 INASOFT/T.Yabuki
# 50秒おきに、マウスを微妙に左右に揺らし、スクリーン セーバー等への移行の阻止を試みます。

$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

echo "Ctrl+Cで終了します。"

# 永久ループ
while ($true) {
# 50秒スリープ
Start-Sleep 50
# マウス座標を少し左にずらす
$SendMouseClick::mouse_event(0x00000001, -1, 0, 0, 0);
# マウス座標を少し右にずらす
$SendMouseClick::mouse_event(0x00000001, 1, 0, 0, 0);
}


これで、マウスを左右に動かす疑似イベントを繰り返し発生させ、スクリーン セーバーへ入ることを抑止(および、リモートワークのごにょごにょを実現)します。

このPowerShellのスクリプトはこちら(mousefr_ps.zip)から入手できますし、上のスクリプトをコピペしてmousefr.ps1という名前で保存し、コンテキストメニューから「PowerShellで実行」を選んで実行もできます。


こんな感じの画面が出てくれば、後はこっそり動いてくれます。[×]ボタンを押してウィンドウを閉じるか、Ctrl+Cでスクリプトを停止すれば、終了となります。



これだけだと、あんまりプログラミングっぽくない(定数定義とかをちゃんとやりたい)ので、それっぽくしたものをダウンロードページの方に置きました。

マウス移動量が1だと、Skypeが反応してくれないという話があるので、そういう場合はこちら(mousefr_ps.zip)のスクリプト内の$MoveMouseDistance = 1の部分を$MoveMouseDistance = 16にするとかで対応してみたりでいかがかなと思います。

posted by ayacy at 00:00 | Comment(0) | TrackBack(0) | プログラミング
この記事へのコメント

この記事へのトラックバック