14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Windowsの画面ロックをC#で検知する

Posted at

C#で画面ロックと画面ロック解除を検知します。

手法

以下の選択肢があるようです。

  • WTSRegisterSessionNotification
  • SystemEvents.SessionSwitch

WTSRegisterSessionNotification

WtsApi32.dllとやらが必要とのこと。見慣れない子ですね…………。
こちらの記事で解説されています。

MSの公式ドキュメントには

セッション変更通知を受信するように指定されたウィンドウを登録します。

とあるので、WinFormsなりWPFなり何かしらのウィンドウが必須っぽいですね。
しっかりと調べてはいませんが、本当にウィンドウ必須なら画面が要らないケースでも画面の実装を強制されてしまうということになります。個人的には、出来れば選択肢から除外したいです。
また、ググって出て来るサンプルがWinFormsばかりなあたりもなんだか古そうで忌避感が加速します。

SystemEvents.SessionSwitch

こちらは画面不要です。Microsoft.Win32名前空間にいるイベントを使います。
下記コードで検証し、いい感じに動いてくれました。

Program.cs
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での実行結果です。

2022-12-18_17h06_44.png

先日リリースされたばかりの.NET 7でも同様に動きます。

Program.cs (.NET 7.0)
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は画面ロックだけでなくログオンやログオフ、リモート接続なんかもキャッチできるみたいです。

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?