C#で画面ロックと画面ロック解除を検知します。
手法
以下の選択肢があるようです。
- WTSRegisterSessionNotification
- SystemEvents.SessionSwitch
WTSRegisterSessionNotification
WtsApi32.dll
とやらが必要とのこと。見慣れない子ですね…………。
こちらの記事で解説されています。
セッション変更通知を受信するように指定されたウィンドウを登録します。
とあるので、WinFormsなりWPFなり何かしらのウィンドウが必須っぽいですね。
しっかりと調べてはいませんが、本当にウィンドウ必須なら画面が要らないケースでも画面の実装を強制されてしまうということになります。個人的には、出来れば選択肢から除外したいです。
また、ググって出て来るサンプルがWinFormsばかりなあたりもなんだか古そうで忌避感が加速します。
SystemEvents.SessionSwitch
こちらは画面不要です。Microsoft.Win32名前空間にいるイベントを使います。
下記コードで検証し、いい感じに動いてくれました。
using Microsoft.Win32;
using System;
namespace ScreenLockObserver {
internal class Program {
static void Main(string[] args) {
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
for (; ; );
}
private static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) {
switch (e.Reason) {
case SessionSwitchReason.SessionLock:
Console.WriteLine(DateTime.Now + ":画面ロック");
break;
case SessionSwitchReason.SessionUnlock:
Console.WriteLine(DateTime.Now + ":画面ロック解除");
break;
}
}
}
}
Windows 11、.NET Framework 4.7.2での実行結果です。
先日リリースされたばかりの.NET 7でも同様に動きます。
using Microsoft.Win32;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
for (; ; );
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) {
switch (e.Reason) {
case SessionSwitchReason.SessionLock:
Console.WriteLine(DateTime.Now + ":画面ロック");
break;
case SessionSwitchReason.SessionUnlock:
Console.WriteLine(DateTime.Now + ":画面ロック解除");
break;
}
}
(最近のC#はMain関数を省略できるのでプロジェクトテンプレートが勝手にMain()を省略しやがるんですが、なかなか慣れないですね……)
おわり
何かしら事情があったり既にWinFormsの画面があったりする場合を除き、SystemEvents.SessionSwitch
がいいかな~と思います。
余談になりますが、SystemEvents.SessionSwitch
は画面ロックだけでなくログオンやログオフ、リモート接続なんかもキャッチできるみたいです。