首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

Windows 關機/重啟/登出 API 完整指南:從 Win9x 到 NT 核心的權限與實現

     編輯:VC 教學

系統關機權限與 API 呼叫全解析

程式化關閉 Windows 看似簡單,實則涉及權限提升、API 版本差異、資料同步等細節。本文整理跨版本相容的關機程式碼,解析 NT 核心特權機制與 9x 系列簡單模式的差異。

核心 API:ExitWindowsEx

BOOL ExitWindowsEx(
    UINT uFlags,    // 操作類型
    DWORD dwReason  // 原因代碼
);

常用旗標組合:

  • EWX_SHUTDOWN | EWX_POWEROFF:關機並切斷電源 (ACPI)
  • EWX_REBOOT:重新開機
  • EWX_LOGOFF:登出當前使用者
  • EWX_FORCE:強制關閉應用程式 (不存檔)
  • EWX_FORCEIFHUNG:僅強制關閉無回應程式

NT 核心 (NT/2000/XP/2003/Vista/7/10/11) 必須提升權限

關機屬於高危操作,需要 SE_SHUTDOWN_NAME 特權。完整流程:

HANDLE hToken;
TOKEN_PRIVILEGES tkp;

// 1. 開啟進程權杖
OpenProcessToken(GetCurrentProcess(), 
                 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

// 2. 查詢特權 LUID
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);

// 3. 設定特權屬性
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

// 4. 調整權杖特權
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);

// 5. 執行關機
ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0);

Win9x 系列 (95/98/Me) 直接呼叫

無特權模型,直接呼叫 ExitWindowsEx 即可。但建議統一程式碼路徑,執行時檢測 OS 版本決定是否提權。

版本檢測與統一封裝範例

bool ShutdownSystem(bool bReboot = false, bool bForce = false) {
    OSVERSIONINFO osvi = { sizeof(osvi) };
    GetVersionEx(&osvi);
    
    UINT flags = bReboot ? EWX_REBOOT : (EWX_SHUTDOWN | EWX_POWEROFF);
    if (bForce) flags |= EWX_FORCE;
    
    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
        // NT 核心提權流程...
        HANDLE hToken; TOKEN_PRIVILEGES tkp;
        if (!OpenProcessToken(GetCurrentProcess(), 
                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            return false;
        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
        tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
    }
    // 9x 或提權後統一呼叫
    return ExitWindowsEx(flags, SHTDN_REASON_MAJOR_OTHER);
}

進階主題

  • 關機封鎖:ShutdownBlockReasonCreate 註冊阻礙原因,使用者可選擇取消/繼續
  • 快速啟動/混合睡眠:Win8+ EWX_HYBRID_SHUTDOWN 核心會話鎖定到磁碟
  • 遠端關機:InitiateSystemShutdownEx 支援遠端機器、倒數計時、自訂訊息
  • 應用程式關機通知:WM_QUERYENDSESSION / WM_ENDSESSION 讓程式存檔/清理

常見失敗原因排查

  1. 權限不足:非管理員/無 SE_SHUTDOWN_NAME
  2. 旗標衝突:EWX_LOGOFF 不能與 EWX_SHUTDOWN 合用
  3. 應用程式攔截:WM_QUERYENDSESSION 回傳 FALSE 取消關機
  4. 快速使用者切換:多會話環境下行為差異

掌握權限提升與版本差異,即可編寫健壯的跨平台關機工具。

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