はじめに
PCをスリープにはせず画面だけオフにするショートカットをつくりました。
これの何がうれしいかというと、モニタを電源を切らずに画面をオフにでき、マウスやキーボードの操作だけで復帰することできます。
(ちなみにノートPCであれば画面を閉じたときの動作で画面だけオフが選べるはずです)
用途としてはPCで動画を再生しながら寝たいときや、大きめのファイルのダウンロードやインストール作業を寝てる裏で実行するみたいな状況を想定しています。
注意事項
- Windows専用
- Macの場合はホットコーナー機能に「ディスプレイをスリープさせる」を割り当てるのが一番簡単かなと思います(参考)
- PowerShellスクリプトの実行ポリシーがRemoteSignedかこれよりも緩い設定になっていること
- 実行ポリシーについてはこちらを参照
- 企業や学校等の組織によってPCの状態を細かく監視されているとアラートが上がる可能性がある
- コマンドラインからPowerShellを実行しているショートカットである点や、オブジェクトの参照値を渡しているところでメモリアクセスが発生している点などから、もしかするとPCのセキュリティチェックに引っかかるかもしれません(1敗)
- 危険なコマンドではないので、もし引っかかった場合はきちんと説明して今後使用しないことを伝えれば問題ないと思います。
作り方
デスクトップやエクスプローラ上で右クリック > 新規作成 > ショートカットと進んで、項目の場所を入力するときに以下のコードを貼り付ければ完成です。
powershell -Command &{sleep 2;sal o New-Object;$f='System.Windows.Forms';Add-Type -AssemblyName $f;$m=(o \"$f.Message\")::Create((o \"$f.Form\").Handle,274,61808,2);(o \"$f.NativeWindow\").DefWndProc([ref]$m);}
あとはこのショートカットを実行するだけで画面をOFFにできます。
解説
基本処理
処理内容はこの記事などを参考にしています。ただ文字数削減のためにNew-Object
コマンドに1文字エイリアスを設定したり、型名を変数にいれて使いまわしたりしています。
最初のsleep 2
は画面をオフにするまでの猶予時間で、ショートカットをクリックした後のちょっとしたマウスの動きですぐに画面オフが解除されてしまうことへの対策として入れています。使い方によってはこの処理はなくても問題ないです。
パス文字列の長さ制限
Windowsはデフォルトだとパス文字列の長さが260文字に制限されています。これはショートカットも同じで、ショートカットのリンク先パス文字列も260文字以内である必要があります。
上記のコードではPowerShellの呼び出しを省略形のpowershell
にしていますが、ショートカットとしての正式なパスはC:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
となります。(PowerShellのバージョンによってはパスが異なると思います)
なのでこのフルパスの分だけスクリプトに使える文字数が減るという制限があり、そのためにわかりにくい1文字エイリアスを設定しているという次第です。
ちなみにパス文字列の長さ制限はレジストリ値を変更することで解除することができます。(参考)
コマンド引数
powershell.exeは引数でコマンド文を直接渡すことができます。
powershell.exe -Command "Write-Host 'Hello, World!'"
powershell.exe -Command &{Write-Host 'Hello, World!'}
コマンド文は文字列として渡すかスクリプトブロックとして渡すことができます。
ここで、勘のいい方は「ダブルクォートで変数展開したいときはエスケープが必要そうだな」などと思うでしょう。もちろん?自分もそう思ったのですがエスケープの方法が特殊で解決するのに時間がかかってしまいました。
結論から言うと以下のようにエスケープする必要がありました。
powershell.exe -Command "$msg = 'Hello'; Write-Host `\"$msg`\""
powershell.exe -Command &{$msg = 'Hello'; Write-Host \"$msg\"}
詳しいことはこちらの記事に書いてありますが、-Commandで渡された文字列はまずコマンドプロンプトの処理系を通ることになり、そこではバックスラッシュでのエスケープが必要になるそうです。
なのでコマンド引数でダブルクォートを含むコマンド文字列を渡す場合は、まずバックスラッシュでエスケープして、それに加えてバッククォートでエスケープする必要があるわけです。
おわりに
モニターだけオフにするという処理にどれだけ需要があるのかわからないですが、たとえニッチな需要だとしても、この記事が何かの助けになるのであれば幸いです。