在Windows 7中使用Win32应用程序禁用CONTROL + ALT + DELETE和Windows(win)键

6

我正在编写一个类似于 kiosk 的应用程序,允许用户退出应用。在 Windows 7 中,当用户按下 Win 键或者 Ctrl+Alt+Delete 组合键时,程序会被退出。我需要通过编程的方式禁用 Windows 7 中的 Ctrl+Alt+Delete 组合键和 Win 键。


3
你可以试着在ServerFault上提出这个问题,那里有办法通过策略将Windows设置为kiosk模式。我建议你这样做会更有成功的机会。 - RobS
3个回答

14
按下Alt+Tab也可以退出应用程序。Ctrl+Esc是打开“开始”菜单的备选快捷方式。Alt+Esc在正在运行的应用程序之间切换。有许多不同的按键序列可以完成此操作,这是Windows作为多任务操作系统的自然结果。
要解决这个问题,您需要安装一个低级键盘钩子来捕获这些任务键。该钩子将监视用于切换任务的任何常见按键序列。每当检测到这些序列之一时,它将通过不向下传递输入来忽略输入。Paul DiLascia在MSDN杂志的2002年9月版中撰写了一篇关于这个问题的文章。您关心的部分大约在页面中部开始,但我在这里重印它以方便起见并为了得到语法高亮的乐趣:
TaskKeyHook.h:
////////////////////////////////////////////////////////////////
// MSDN Magazine — September 2002
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 6.0 and Visual Studio .NET on Windows XP.
//
#define DLLIMPORT __declspec(dllimport)

DLLIMPORT BOOL DisableTaskKeys(BOOL bEnable, BOOL bBeep);
DLLIMPORT BOOL AreTaskKeysDisabled();

TaskKeyHook.cpp

////////////////////////////////////////////////////////////////
// MSDN Magazine — September 2002
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio 6.0 and Visual Studio .NET on Windows XP.
//
// This file implements the low-level keyboard hook that traps the task 
// keys.
//
#define _WIN32_WINNT 0x0500 // for KBDLLHOOKSTRUCT
#include <afxwin.h>         // MFC core and standard components

#define DLLEXPORT __declspec(dllexport)

//////////////////
// App (DLL) object
//
class CTaskKeyHookDll : public CWinApp {
public:
   CTaskKeyHookDll()  { }
   ~CTaskKeyHookDll() { }
} MyDll;

////////////////
// The section is SHARED among all instances of this DLL.
// A low-level keyboard hook is always a system-wide hook.
// 
#pragma data_seg (".mydata")
HHOOK g_hHookKbdLL = NULL; // hook handle
BOOL  g_bBeep = FALSE;     // beep on illegal key
#pragma data_seg ()
#pragma comment(linker, "/SECTION:.mydata,RWS") // tell linker: make it 
                                                // shared

/////////////////
// Low-level keyboard hook:
// Trap task-switching keys by returning without passing along.
//
LRESULT CALLBACK MyTaskKeyHookLL(int nCode, WPARAM wp, LPARAM lp)
{
   KBDLLHOOKSTRUCT *pkh = (KBDLLHOOKSTRUCT *) lp;

   if (nCode==HC_ACTION) {
      BOOL bCtrlKeyDown =
         GetAsyncKeyState(VK_CONTROL)>>((sizeof(SHORT) * 8) - 1);

      if ((pkh->vkCode==VK_ESCAPE && bCtrlKeyDown) || // Ctrl+Esc
          // Alt+TAB
          (pkh->vkCode==VK_TAB && pkh->flags & LLKHF_ALTDOWN) ||   
          // Alt+Esc
          (pkh->vkCode==VK_ESCAPE && pkh->flags & LLKHF_ALTDOWN)|| 
          (pkh->vkCode==VK_LWIN || pkh->vkCode==VK_RWIN)) { // Start Menu
         if (g_bBeep && (wp==WM_SYSKEYDOWN||wp==WM_KEYDOWN))
            MessageBeep(0); // only beep on downstroke if requested
         return 1; // gobble it: go directly to jail, do not pass go
      }
   }
   return CallNextHookEx(g_hHookKbdLL, nCode, wp, lp);
}

//////////////////
// Are task keys disabled—ie, is hook installed?
// Note: This assumes there's no other hook that does the same thing!
//
DLLEXPORT BOOL AreTaskKeysDisabled()
{
   return g_hHookKbdLL != NULL;
}

//////////////////
// Disable task keys: install low-level kbd hook.
// Return whether currently disabled or not.
//
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 != NULL) {
      UnhookWindowsHookEx(g_hHookKbdLL);
      g_hHookKbdLL = NULL;
   }
   g_bBeep = bBeep;

   return AreTaskKeysDisabled();
}

他还提供了示例代码以禁用任务栏(从而防止Windows键显示开始菜单),以及使用这些库的完整示例应用程序。
至于防止Ctrl+Alt+Del(安全注意序列或SAS),上述方法是行不通的。原因是操作系统将由SAS生成的硬件中断与其他键分开捕获,特别是为了防止程序挂钩该序列并欺骗登录提示。您无法使用键盘挂钩禁用此功能。我在上面链接的文章在顶部详细介绍了这个要求,但这些策略仅经过测试,很可能只适用于Windows XP。文章建议的另一种方法是禁用任务管理器,但请注意,这不会阻止用户关闭系统等操作。正确的做法是编写键盘驱动程序。

谢谢Cody...我已经使用msgina.dll让它工作了...感谢你详细的回答... - Rajesh Subramanian
Msgina 在 Windows 7 上可以使用吗? - SparcU
@SparcU:不,Windows Vista或更高版本(包括Windows 7)中没有msgina。这已经超出了Windows XP的选项。 - Cody Gray
"钩子必须作为DLL实现",不对啊。你有证据吗? - IronManMark20
@IronManMark20 可以证实在Win 10上,这不需要放在DLL中。将“ MyDll.m_hInstance”替换为“ GetModuleHandle(NULL)”即可解决问题。 - travisjayday
之前的评论者是正确的。低级键盘(和鼠标)钩子是Windows钩子必须在DLL中实现的例外情况。那是我犯的一个错误。我已经更新了答案。迟做总比不做好。 - Cody Gray

1
据我所知,在win32中无法捕获CTRL + ALT + DELETE键组合。不过,如果你愿意的话,有一些绕过这个问题的方法。

我试图捕捉组合,但从未成功过... - Rajesh Subramanian

0

我认为可以通过替换主Windows键盘驱动程序kbdclass.sys来实现。在其内部,应该可以处理Delete键的按下,并且例如当Ctrl和Alt键已经按下时,避免将其进一步传递。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接