首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 捕捉 Windows 關機事件:打造防忘記簽退的提醒小工具

     編輯:關於C#

緣起

下班前常忘記簽退?想寫一個小程式,在 Windows 關機或登出時跳出提醒視窗,確認是否已完成簽退。這篇文章分享如何使用 Microsoft.Win32.SystemEvents.SessionEnding 事件實作這個需求,並討論兩個已知缺點與可能的改進方向。

核心技術:SystemEvents.SessionEnding

SystemEvents.SessionEnding 是一個靜態事件,當使用者登出、關機或重新開機時觸發。需注意:

  • 僅在 Windows Forms 應用程式中有效,Console 應用程式無法接收此事件。
  • 程式結束時務必移除事件訂閱(-=),否則會造成記憶體洩漏。

完整程式碼範例

Program.cs - 進入點

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

namespace ShutdownReminder
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            FormShutdown formShutdown = new FormShutdown();
            // 訂閱 SessionEnding 事件
            SystemEvents.SessionEnding += new SessionEndingEventHandler(formShutdown.SystemEvents_SessionEnding);
            Application.Run(formShutdown);
        }
    }
}

FormShutdown.cs - 主視窗邏輯

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

namespace ShutdownReminder
{
    public partial class FormShutdown : Form
    {
        const string MESSAGE_TXT = "您簽退了嗎?";
        const string MESSAGE_TITLE = "提示";

        public FormShutdown()
        {
            InitializeComponent();
        }

        // 事件處理函式
        internal void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
        {
            DialogResult result = MessageBox.Show(MESSAGE_TXT, MESSAGE_TITLE, MessageBoxButtons.YesNo);
            // 若使用者選「否」,取消關機/登出
            e.Cancel = (result == DialogResult.No);
        }

        private void FormShutdown_Load(object sender, EventArgs e)
        {
            // 將視窗移至螢幕右上角(不干擾操作)
            this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - 200, 0);
        }

        // 表單關閉時移除事件訂閱,防止記憶體洩漏
        protected override void OnClosed(EventArgs e)
        {
            SystemEvents.SessionEnding -= new SessionEndingEventHandler(this.SystemEvents_SessionEnding);
            base.OnClosed(e);
        }
    }
}

測試環境與結果

  • 開發環境:C# 2.0 / Visual Studio 2005
  • 測試平台:Windows Server 2003
  • 結果:關機/登出時成功彈出提醒視窗,選「否」可取消關機。

已知缺點

  1. 無法捕捉休眠/喚醒事件:SessionEnding 僅涵蓋登出、關機、重開機,不包含睡眠/休眠狀態轉換。
  2. 記憶體佔用偏高:一個只有提醒功能的小程式卻佔用約 12 MB 記憶體,主要是 .NET Framework 執行環境的基礎開銷。

改進方向討論

針對上述缺點,社群常見的替代方案包括:

  • 使用 WMI (System.Management) 監聽 Win32_OperatingSystem 的關機事件,可在服務或主控台應用程式中運作,且不需載入 WinForms 組件,記憶體佔用較低。
  • 撰寫 Windows Service 並透過 ServiceBase.CanHandleSessionChangeEvent 處理 Session 變更,支援更多事件類型(含鎖定/解鎖、遠端連線等)。
  • P/Invoke 註冊系統熱鍵或 Hook:更底層,但複雜度高,需權衡維護成本。

結語

SystemEvents.SessionEnding 提供最簡單的方式在 WinForms 應用程式中攔截關機流程,適合快速原型或內部小工具。若需部署正式環境、支援休眠事件或追求極低資源佔用,建議改用 WMI 或 Windows Service 架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved