在自助終端機、考試系統、工業控制、數位看板等專用場景,必須防止使用者透過 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 + 應用程式原始碼。
gpedit.msc 開啟群組原則編輯器。
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\PoliciesHKCU\Software\Microsoft\Windows\CurrentVersion\PoliciesHKLM\Software\PoliciesHKLM\Software\Microsoft\Windows\CurrentVersion\PoliciesWH_KEYBOARD_LL (Low-Level Hook)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。HWND hTray = FindWindow(_T("Shell_TrayWnd"), NULL);
if (hTray) EnableWindow(hTray, FALSE); // 停用
// 恢復: EnableWindow(hTray, TRUE);
注意:即使停用工作列,Win 鍵仍可能彈出開始功能表 (Explorer 內部處理)。因此必須配合方案二攔截 VK_LWIN/VK_RWIN。
CTaskKeyMgrclass 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.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();
}
TaskKeyHook.dll 需置於應用程式目錄或系統路徑。HKCU\...\Policies\System 需當前使用者權限;若需機器級生效,改寫 HKLM 需管理員權限。HKLM 且可能受群組原則覆蓋。VK_ESCAPE + VK_CONTROL + VK_SHIFT 組合,或配合軟體限制原則 (SRP) 禁止 taskmgr.exe 執行。OutputDebugString 觀察攔截狀況,避免在鉤子中執行耗時操作 (如 MessageBox、檔案 I/O) 導致系統輸入延遲。taskmgr.exe:映像劫持 (IFEO) 將 taskmgr.exe 重導向自訂程式,屬於「欺騙」手法,不屬正統攔截。「登錄策略禁用工作管理器」+「低階鍵盤鉤子攔截切換/Win 鍵」+「停用工作列視窗」構成 Windows XP/2000 專用場景下最實用、最穩定的系統熱鍵封鎖方案。本文提供的 TaskKeyHook.dll + CTaskKeyMgr 封裝,可直接整合至 MFC/SDK 專案,透過位元旗標靈活控制三大功能的啟停。部署時請務必配合權限管理與系統還原機制,確保應用程式異常退出時仍能自動恢復使用者環境。