You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6中Microsoft.Win32.SystemEvents是否可用?会话切换检测方案

.NET 6中处理Windows会话切换的方案

1. Microsoft.Win32.SystemEvents的可用性

Microsoft.Win32.SystemEvents在.NET 6中完全可用,它从.NET Core 3.0开始就被支持,但仅针对Windows平台。使用前需注意:

  • WinForms、WPF这类自带消息循环的UI应用,可直接订阅事件;
  • 控制台、无UI服务类应用,需要手动启动Windows消息循环,否则事件无法触发。

2. 实现会话切换检测的具体方案

方案一:使用SystemEvents(推荐UI应用)

直接订阅SessionSwitch事件,处理登录、注销等会话切换场景:

using Microsoft.Win32;

// 订阅事件
SystemEvents.SessionSwitch += OnSessionSwitch;

private void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
{
    switch (e.Reason)
    {
        case SessionSwitchReason.SessionLogon:
            // 执行登录后的逻辑
            break;
        case SessionSwitchReason.SessionLogoff:
            // 执行注销后的逻辑
            break;
        // 可额外处理SessionLock、SessionUnlock等场景
    }
}

// 应用退出时取消订阅,避免内存泄漏
SystemEvents.SessionSwitch -= OnSessionSwitch;

如果是控制台应用,需引用System.Windows.Forms包,手动启动消息循环:

using Microsoft.Win32;
using System.Windows.Forms;

class Program
{
    static void Main(string[] args)
    {
        SystemEvents.SessionSwitch += OnSessionSwitch;
        // 启动消息循环维持应用运行
        Application.Run();
    }

    private static void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
    {
        switch (e.Reason)
        {
            case SessionSwitchReason.SessionLogon:
                Console.WriteLine("用户已登录");
                break;
            case SessionSwitchReason.SessionLogoff:
                Console.WriteLine("用户已注销");
                break;
        }
    }
}

方案二:使用Windows API(适合服务/无UI应用)

通过P/Invoke调用WTSRegisterSessionNotification监听会话通知,无需依赖UI框架:

using System;
using System.Runtime.InteropServices;

class SessionMonitor
{
    private const int WM_WTSSESSION_CHANGE = 0x02B1;
    private const int WTS_SESSION_LOGON = 0x5;
    private const int WTS_SESSION_LOGOFF = 0x6;
    private const int NOTIFY_FOR_ALL_SESSIONS = 1;

    [DllImport("Wtsapi32.dll")]
    private static extern bool WTSRegisterSessionNotification(IntPtr hWnd, int dwFlags);

    [DllImport("Wtsapi32.dll")]
    private static extern bool WTSUnRegisterSessionNotification(IntPtr hWnd);

    [DllImport("User32.dll")]
    private static extern IntPtr CreateWindowEx(int dwExStyle, string lpClassName, string lpWindowName, int dwStyle,
        int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

    [DllImport("User32.dll")]
    private static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);

    [DllImport("User32.dll")]
    private static extern bool TranslateMessage(ref MSG lpMsg);

    [DllImport("User32.dll")]
    private static extern IntPtr DispatchMessage(ref MSG lpMsg);

    private struct MSG
    {
        public IntPtr hwnd;
        public uint message;
        public IntPtr wParam;
        public IntPtr lParam;
        public uint time;
        public POINT pt;
    }

    private struct POINT
    {
        public int x;
        public int y;
    }

    public static void StartMonitoring()
    {
        // 创建隐藏窗口接收系统消息
        var hwnd = CreateWindowEx(0, "Static", "", 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
        
        if (WTSRegisterSessionNotification(hwnd, NOTIFY_FOR_ALL_SESSIONS))
        {
            MSG msg;
            while (GetMessage(out msg, IntPtr.Zero, 0, 0))
            {
                if (msg.message == WM_WTSSESSION_CHANGE)
                {
                    var sessionEvent = (int)msg.wParam;
                    switch (sessionEvent)
                    {
                        case WTS_SESSION_LOGON:
                            Console.WriteLine("用户登录");
                            break;
                        case WTS_SESSION_LOGOFF:
                            Console.WriteLine("用户注销");
                            break;
                    }
                }
                TranslateMessage(ref msg);
                DispatchMessage(ref msg);
            }
            WTSUnRegisterSessionNotification(hwnd);
        }
    }
}

// 使用示例
class Program
{
    static void Main(string[] args)
    {
        SessionMonitor.StartMonitoring();
    }
}

内容的提问来源于stack exchange,提问作者Ventsislav Petrov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:15:33