Powershell: キーボードレイアウトを調べる

先日、仕事場の同僚から、「使っているPCに英語キーボードがつながっているか日本語キーボードがつながっているか調べる方ありませんか?」って尋ねられました。

実際に接続されているキーボードを調べることが出来るかどうかは知らないものの、USキーボードを使っている私は、キーボードレイアウトはレジストリに格納されていることを知っています。また、Powershell でレジストリを読み出せることも知っています。

つまり、出来そうって事。

では実際どうすればいいか?

答えは、対象PCの「HKLM:\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters」というキーに格納されている、名前「LayerDriver JPN」のデータを読み取ればいいということ。
具体的には、Get-ItemProperty -path で対象キーの値を表示。(以下)

> Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters


PollingIterations          : 12000
PollingIterationsMaximum   : 12000
ResendIterations           : 3
WppRecorder_TraceGuid      : {7ffb8eb8-2c86-45d6-a7c5-c023d9c070c1}
LayerDriver JPN            : kbd101.dll
LayerDriver KOR            : kbd101a.dll
OverrideKeyboardIdentifier : PCAT_101KEY
OverrideKeyboardType       : 7
OverrideKeyboardSubtype    : 0
PSPath                     : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters
PSParentPath               : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt
PSChildName                : Parameters
PSDrive                    : HKLM
PSProvider                 : Microsoft.PowerShell.Core\Registry

実際やってみると、LayerDriver と JPN の間にスペースが入っている!

これ、どうやって指定するの?例えば、PSDriveのデータを知りたければ、

(Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters).PSDrive

と書けばいいのですけど、PSDriveはひと続き。間にスペースがある名前はどう指定する?

試行錯誤した結果、名前をシングルクォートで囲めばいいって事のようです。変数にしてしまうという手もあるのかな〜?と思いましたけど、これは駄目みたい。

(Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters).'LayerDriver JPN'
kbd101.dll

これをリモートPCに対して行おうとすると、Invoke-Command で囲めばいいので、以下のような感じになるはず。ドメイン参加PCなら、認証は不要かもしれませんが、ワークグループだと、以下の赤部分、-Credential で管理者情報を入力しないとリモートレジストリの値は読み出せないかもしれません。

$c = Get-Credential
$target = "pc_name"
(Invoke-Command -ComputerName $target -Credential $c -ScriptBlock { Get-ItemProperty -path HKLM:\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters }).'LayerDriver JPN'

あとは、読み出した値が、kbd101.dll か kbd106.dll かを判断すればいいってことになるはずです。

試してみると、一応値は読み出せましたが、invoke-command は実行が遅い遅い。

他にもっとスマートな方法があるかもしれませんが、今はこれ以上調べる気にならないので、これをメモしておくことにしました。

コメントを残す