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

Windows XP/2000 系統熱鍵攔截完全指南:屏蔽 Ctrl+Alt+Del、Alt+Tab、Win 鍵與工作列

     編輯:關於VC++

前言:為何需要攔截系統熱鍵

在自助終端機、考試系統、工業控制、數位看板等專用場景,必須防止使用者透過 Ctrl+Alt+Del 呼叫工作管理器、Alt+Tab 切換視窗、Win 鍵彈出開始功能表、或操作工作列。Windows 9x 時代可用 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING) 粗暴屏蔽,但 NT 核心系統 (NT 4.0 SP3+/2000/XP) 採用 Winlogon/GINA 架構,需更精細的攔截手段。本文系統介紹三種層級的解決方案:群組原則/登錄 (針對工作管理器)、低階鍵盤鉤子 (攔截 Alt+Tab/Win/Escape 組合)、工作列視窗停用,並提供完整可編譯的 DLL + 應用程式原始碼。

方案一:禁用工作管理器 (Ctrl+Alt+Del) — 群組原則與登錄

圖形介面操作

  1. 執行 gpedit.msc 開啟群組原則編輯器。
  2. 展開:使用者設定 → 管理範本 → 系統 → Ctrl+Alt+Del 選項。
  3. 啟用「移除工作管理器」。

群組原則編輯器禁用工作管理器

登錄對應鍵值 (程式化部署)

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System
    DisableTaskMgr = DWORD:1   // 1=禁用, 0/刪除=啟用

設定後,按下 Ctrl+Alt+Del 將彈出「系統管理員已停用工作管理器」錯誤對話框。

禁用後的錯誤提示

前置條件:歡迎畫面啟用

控制台 → 使用者帳戶 → 變更使用者登入/登出方式 → 勾選「使用歡迎畫面」。若使用傳統登入,Ctrl+Alt+Del 仍會彈出傳統安全性對話框,僅工作管理器按鈕變灰。

登入選項設定

原理溯源:system.adm 範本

CATEGORY !!CADOptions
KEYNAME "Software\Microsoft\Windows\CurrentVersion\Policies\System"
POLICY !!DisableTaskMgr
VALUENAME "DisableTaskMgr"
END POLICY
END CATEGORY

所有群組原則最終皆落實為上述四個登錄根鍵之一的 Policies 子樹:

  • HKCU\Software\Policies
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Policies
  • HKLM\Software\Policies
  • HKLM\Software\Microsoft\Windows\CurrentVersion\Policies

方案二:低階鍵盤鉤子攔截 Alt+Tab、Ctrl+Esc、Win 鍵、Alt+Esc

為何必須用 WH_KEYBOARD_LL (Low-Level Hook)

  • 全域攔截,不依賴特定執行緒訊息佇列。
  • 在鍵盤輸入到達目標視窗前處理,可直接返回非零值阻斷傳遞。
  • DLL 必須將鉤子變數置於共享資料段,確保多進程實例共用同一鉤子句柄。

鍵盤鉤子 DLL 完整原始碼 (TaskKeyHook.cpp)

#define _WIN32_WINNT 0x0500   // 啟用 KBDLLHOOKSTRUCT
#include 

#define DLLEXPORT __declspec(dllexport)

#pragma data_seg(".mydata")
HHOOK g_hHookKbdLL = NULL;    // 共享鉤子句柄
BOOL  g_bBeep = FALSE;        // 共享蜂鳴旗標
#pragma data_seg()
#pragma comment(linker, "/SECTION:.mydata,RWS")  // 告知連結器建立可讀寫共享段

class CTaskKeyHookDll : public CWinApp { } MyDll;

// 低階鍵盤鉤子處理函數
LRESULT CALLBACK MyTaskKeyHookLL(int nCode, WPARAM wp, LPARAM lp) {
    if (nCode != HC_ACTION) return CallNextHookEx(g_hHookKbdLL, nCode, wp, lp);

    KBDLLHOOKSTRUCT* pkh = (KBDLLHOOKSTRUCT*)lp;
    BOOL bCtrl = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;

    // 攔截目標組合鍵
    if ( (pkh->vkCode == VK_ESCAPE && bCtrl) ||                    // Ctrl+Esc
         (pkh->vkCode == VK_TAB && (pkh->flags & LLKHF_ALTDOWN)) || // Alt+Tab
         (pkh->vkCode == VK_ESCAPE && (pkh->flags & LLKHF_ALTDOWN)) || // Alt+Esc
         (pkh->vkCode == VK_LWIN || pkh->vkCode == VK_RWIN) ) {    // Win 鍵
        if (g_bBeep && (wp == WM_KEYDOWN || wp == WM_SYSKEYDOWN))
            MessageBeep(0);
        return 1;  // 阻斷傳遞,不呼叫 CallNextHookEx
    }
    return CallNextHookEx(g_hHookKbdLL, nCode, wp, lp);
}

// 匯出函數:安裝/移除鉤子
DLLEXPORT BOOL DisableTaskKeys(BOOL bDisable, BOOL bBeep) {
    if (bDisable) {
        if (!g_hHookKbdLL) {
            g_hHookKbdLL = SetWindowsHookEx(WH_KEYBOARD_LL, MyTaskKeyHookLL,
                                           MyDll.m_hInstance, 0);
        }
    } else if (g_hHookKbdLL) {
        UnhookWindowsHookEx(g_hHookKbdLL);
        g_hHookKbdLL = NULL;
    }
    g_bBeep = bBeep;
    return g_hHookKbdLL != NULL;
}

DLLEXPORT BOOL AreTaskKeysDisabled() {
    return g_hHookKbdLL != NULL;
}

關鍵技術點解析

  • #pragma data_seg(".mydata") + #pragma comment(linker, "/SECTION:.mydata,RWS"):建立跨進程共享的全域變數區,確保所有載入 DLL 的進程看到相同的 g_hHookKbdLL。
  • KBDLLHOOKSTRUCT 包含 vkCode (虛擬鍵碼)、flags (含 LLKHF_ALTDOWN 等)、time、dwExtraInfo。
  • 使用 GetAsyncKeyState(VK_CONTROL) 檢查 Ctrl 鍵狀態,因低階鉤子不保證修飾鍵順序。
  • 返回 1 (非零) 即阻斷訊息傳遞,不呼叫 CallNextHookEx。

方案三:停用工作列 (Shell_TrayWnd)

HWND hTray = FindWindow(_T("Shell_TrayWnd"), NULL);
if (hTray) EnableWindow(hTray, FALSE);  // 停用
// 恢復: EnableWindow(hTray, TRUE);

注意:即使停用工作列,Win 鍵仍可能彈出開始功能表 (Explorer 內部處理)。因此必須配合方案二攔截 VK_LWIN/VK_RWIN。

整合管理類別 CTaskKeyMgr

class CTaskKeyMgr {
public:
    enum { TASKMGR = 0x01, TASKKEYS = 0x02, TASKBAR = 0x04, ALL = 0xFFFF };

    static void Disable(DWORD dwFlags, BOOL bDisable, BOOL bBeep = FALSE) {
        if (dwFlags & TASKMGR) {
            // 登錄操作 (同上方案一)
            HKEY hk; RegCreateKey(HKEY_CURRENT_USER, KEY_DisableTaskMgr, &hk);
            if (bDisable) { DWORD v=1; RegSetValueEx(hk, VAL_DisableTaskMgr, 0, REG_DWORD, (BYTE*)&v, 4); }
            else RegDeleteValue(hk, VAL_DisableTaskMgr);
            RegCloseKey(hk);
        }
        if (dwFlags & TASKKEYS) ::DisableTaskKeys(bDisable, bBeep);  // 呼叫 DLL
        if (dwFlags & TASKBAR) {
            HWND h = FindWindow(_T("Shell_TrayWnd"), NULL);
            if (h) EnableWindow(h, !bDisable);
        }
    }
    static BOOL IsTaskMgrDisabled()  { /* 查詢登錄 */ }
    static BOOL IsTaskBarDisabled()  { HWND h=FindWindow(_T("Shell_TrayWnd"),NULL); return h && !IsWindowEnabled(h); }
    static BOOL AreTaskKeysDisabled() { return ::AreTaskKeysDisabled(); }
};

示範應用程式 (TrapKeys.exe) 介面

對話框包含三組核取方塊:禁用工作管理器、禁用任務切換鍵、禁用工作列。狀態即時同步顯示。程式結束時自動恢復所有設定。

TrapKeys 程式運行畫面

核心邏輯 (TrapKeys.cpp 節錄)

void CMyDialog::OnDisableTaskKeys() {
    CTaskKeyMgr::Disable(CTaskKeyMgr::TASKKEYS,
        !CTaskKeyMgr::AreTaskKeysDisabled(), TRUE);  // 啟用蜂鳴
}
void CMyDialog::OnUpdateDisableTaskKeys(CCmdUI* pCmdUI) {
    pCmdUI->SetCheck(CTaskKeyMgr::AreTaskKeysDisabled());
}
// 類似處理 TASKMGR、TASKBAR...

// 應用程式結束時恢復
int CMyApp::ExitInstance() {
    CTaskKeyMgr::Disable(CTaskKeyMgr::ALL, FALSE);
    return CWinApp::ExitInstance();
}

部署與注意事項

  1. DLL 與 EXE 同目錄:TaskKeyHook.dll 需置於應用程式目錄或系統路徑。
  2. 權限要求:修改 HKCU\...\Policies\System 需當前使用者權限;若需機器級生效,改寫 HKLM 需管理員權限。
  3. 系統相容性:測試通過 Windows 2000/XP/2003。Vista/7/8/10/11 因 UAC、安全桌面、UIPI 機制,低階鉤子仍有效,但工作管理器禁用需寫 HKLM 且可能受群組原則覆蓋。
  4. 反作弊/防繞過:使用者可透過 Ctrl+Shift+Esc 直接啟動工作管理器 (繞過 Ctrl+Alt+Del),若需完全封鎖,請同步攔截 VK_ESCAPE + VK_CONTROL + VK_SHIFT 組合,或配合軟體限制原則 (SRP) 禁止 taskmgr.exe 執行。
  5. 除錯技巧:在鉤子函數中輸出 OutputDebugString 觀察攔截狀況,避免在鉤子中執行耗時操作 (如 MessageBox、檔案 I/O) 導致系統輸入延遲。

替代方案簡述

  • 自訂 GINA (msgina.dll 替換):NT 4.0/2000 時代方案,Vista 後棄用 (改用 Credential Provider),維護成本極高,不建議新專案採用。
  • 鍵盤驅動程式過濾器:核心模式,權限最高,但開發難度大、簽章部署複雜、穩定性風險高。
  • 替換 taskmgr.exe:映像劫持 (IFEO) 將 taskmgr.exe 重導向自訂程式,屬於「欺騙」手法,不屬正統攔截。

結語

「登錄策略禁用工作管理器」+「低階鍵盤鉤子攔截切換/Win 鍵」+「停用工作列視窗」構成 Windows XP/2000 專用場景下最實用、最穩定的系統熱鍵封鎖方案。本文提供的 TaskKeyHook.dll + CTaskKeyMgr 封裝,可直接整合至 MFC/SDK 專案,透過位元旗標靈活控制三大功能的啟停。部署時請務必配合權限管理與系統還原機制,確保應用程式異常退出時仍能自動恢復使用者環境。

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