C#|グローバルホットキーを登録するに感銘を受けたので、一部アレンジして、PowerShellから使用できるようにしました。
概要
ホットキーを登録し、登録したキーを押下するとPowerShellコマンドが実行できるようにします。
実装
クラス定義(C#)
hotkeyClass.cs
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
//クラス(ホットキー登録・解除用フォーム)
public class HotKeyForm : Form
{
[DllImport("user32.dll")]
extern static int RegisterHotKey(IntPtr HWnd, int ID, int MOD_KEY, Keys KEY);
[DllImport("user32.dll")]
extern static int UnregisterHotKey(IntPtr HWnd, int ID);
const int WM_HOTKEY = 0x0312;
public readonly int modKey;
public readonly Keys key;
public readonly int id;
public readonly ThreadStart proc;
//ホットキー登録
public HotKeyForm(int modKey, Keys key, ThreadStart proc)
{
for (int i = 0x0000; i <= 0xbfff; i++)
{
if (RegisterHotKey(this.Handle, i, modKey, key) != 0)
{
this.modKey = modKey;
this.key = key;
this.id = i;
this.proc = proc;
break;
}
}
}
//ウィンドウメッセージ監視
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
//ホットキーが押された時の処理
if (m.Msg == WM_HOTKEY)
{
if ((int)m.WParam == this.id)
{
this.proc();
}
}
}
//ホットキー解除
protected override void Dispose(bool disposing)
{
UnregisterHotKey(this.Handle, this.id);
base.Dispose(disposing);
}
}
//クラス(ホットキー制御用フォーム)
public class HotKeyController : Form
{
public List<HotKeyForm> HotKeyFormList;
//ホットキー登録・解除用フォームを表示すると、ウィンドウメッセージの監視が開始される
private void HotKeyController_Load(object sender,EventArgs e)
{
foreach (HotKeyForm hotKeyForm in this.HotKeyFormList)
{
hotKeyForm.WindowState = System.Windows.Forms.FormWindowState.Minimized;
hotKeyForm.Show();
hotKeyForm.Hide();
}
}
private void HotKeyController_FormClosing(object sender,EventArgs e)
{
foreach (HotKeyForm hotKeyForm in this.HotKeyFormList)
{
if (!hotKeyForm.IsDisposed)
{
hotKeyForm.Close();
}
}
}
public HotKeyController()
{
this.HotKeyFormList = new List<HotKeyForm>();
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
this.ShowInTaskbar = false;
this.Load += HotKeyController_Load;
this.FormClosing += HotKeyController_FormClosing;
}
}
モジュール定義(PowerShell)
hotkeyModule.ps1
$here = Split-Path $MyInvocation.MyCommand.Path -Parent
New-Module -ArgumentList $here {
param($here)
# --------------------
# 非公開定義
# --------------------
# ホットキー登録・監視用クラス(C#)
Add-Type `
-ReferencedAssemblies 'System.Windows.Forms' `
-Path (Join-Path $here 'hotkeyClass.cs')
# 修飾キー
$MODKEY_LIST = @{
ALT = 0x0001;
CTRL = 0x0002;
SHIFT = 0x0004;
_ = 0x0000;
}
# ハッシュテーブルを検索
filter Select-HashTable{
param(
[Alias('with')][hashtable]$HashTable,
$DefaultKey = '_'
)
if($HashTable.Contains($_)){
return $HashTable[$_]
} else {
return $HashTable[$DefaultKey]
}
}
Set-Alias match Select-HashTable
# キー文字列を修飾キーとキーコードへ変換
function ConvertTo-HotKeyArguments($KeyString){
# キー文字列をリスト化
# 例)Ctrl + A -> CTRL,A
$KeyList = $KeyString.ToUpper().Split('+') | foreach{$_.Trim()}
# 修飾キー(全て取得)
$modkey = ($KeyList | match -with $MODKEY_LIST) -join ' -bor ' | iex
# キーコード(初めの1つだけ取得)
$key = ($KeyList | where{-not ($MODKEY_LIST.Contains($_))} | foreach{[Windows.Forms.Keys]::"$_"})[0]
return $modkey,$key
}
Set-Alias hkargs ConvertTo-HotKeyArguments
# --------------------
# 公開定義
# --------------------
# ホットキーを登録し、ホットキーが押下された時に指定のコマンドを実行
function Watch-HotKey($HotKeyList,$CloseKey){
$ctl = New-Object HotKeyController
# 各種ホットキーの登録
$HotKeyList | foreach{
$modKey,$key = hkargs $_.KeyString
$proc = $_.Procedure
$ctl.HotKeyFormList.Add((New-Object HotKeyForm($modKey,$key,$proc)))
}
# 終了用ホットキーの登録
$modKey,$key = hkargs $CloseKey
$proc = {$ctl.Close()}
$ctl.HotKeyFormList.Add((New-Object HotKeyForm($modKey,$key,$proc)))
# ホットキー監視(終了用ホットキーが押下されるまで持続)
[void]$ctl.ShowDialog()
}
Export-ModuleMember -Function Watch-HotKey
}
使用方法
上記のhotkeyModule.ps1を実行しモジュールを登録した後、Watch-Hotkey関数を呼び出してホットキーの登録及び監視を行います。
hotkeyModuleTest.ps1
# モジュール登録
$here = Split-Path $MyInvocation.MyCommand.Path -Parent
& (Join-Path $here 'hotkeyModule.ps1') | Out-Null
# ホットキーの登録及び監視
Watch-HotKey @(
@{KeyString='Ctrl+Shift+L';Procedure={Write-Host '処理1'}},
@{KeyString='Ctrl+Shift+M';Procedure={Write-Host '処理2'}}
) -CloseKey 'Ctrl+W'
まとめ
少しコマンドを実行する程度なら、AutoHotkeyなどのフリーソフトを使うより、PowerShellで組んでしまった方が、(Windows7以降だと)別途インストールが不要な分手軽で良いのかもしれません。
活用例としては、各種アプリケーションの起動、アクティブなプロセスに応じたコマンド実行(Excelマクロ実行など)、マウスカーソルがある座標の色情報取得・・・といった辺りが思いつきます。工夫次第では他にも色々使えそうです。
類似としては、WndProcを使うという点ではクリップボード監視ツールも同じような方法で実装できそうです。
余裕があればチャレンジしたいと思います。