PowerShellでホットキー経由でWinShotを再起動する

WinShotの設定(ファイル名や保存先)をこまめに切り替える作業が面倒になったので自動化できないものか考えた。
環境設定ダイアログで設定を変えるのを自動化するのは難しいと思ったので、WinShot停止→設定ファイル編集→WinShot起動としてみたい。

WinShotの停止はPowerShellのStop-Processコマンドレットを使用すれば実現できる。しかしプロセスの強制停止であるためタスクトレイにアイコンが残留する。
残留したアイコンはマウスオーバーすれば削除されるのだがやはり気持ちが悪い。
というわけで、ホットキーでポップアップメニューを表示させ、そこから停止してみた。

WinShotの設定

ポップアップメニューを「Ctrl + Shift + D」で表示するように設定する。

「Ctrl + Shift + D」でポップアップメニューが表示される。ここでさらに「X」を入力すれば、WinShotは通常の方法で停止する。

PowerShell

PowerShellからキーを入力するところだけがポイントだ。ただし、「Ctrl + Shift + D」のあとに「X」を入力するのだが、万が一ポップアップメニューが表示されないと、意図しないところに「X」が入力される可能性がある。そのため、アクティブになっているウィンドウがWinShotのものなのか、確認を入れた。(Win32APIを直接呼び出す必要があり、書き方はいろいろな例を真似してみた。)

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Win32API {
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
  }
"@

$winshot = Get-Process -name winshot

$p=0
[System.Windows.Forms.SendKeys]::SendWait("^+{d}") 
Start-Sleep -Milliseconds 100
$hwnd = [Win32API]::GetForegroundWindow()
$null = [Win32API]::GetWindowThreadProcessId($hwnd, [ref]$p)

if ( $p -eq $winshot.Id ) {
    [System.Windows.Forms.SendKeys]::SendWait("x") }

Start-Sleep -Milliseconds 500
Start-Process c:\tools\winshot\winshot.exe

WinShotをたかだかタスクトレイの一時的な表示残留程度でこんな止め方をするのは大袈裟すぎる気がするが・・・キー入力の方法とか、Win32APIの呼び出し方法とかはメモしておきたい。

そもそもWinShotのプロセスがなければ「Ctrl + Shift + D」も入力すべきではないし、上記の処理でWinShotが停止しなかった場合にはStop-Processで止める、などの処理を加える必要がある。