.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
相关产品推荐
相关产品推荐

