C# Disable CTRL-ALT-DEL, ALT-TAB, ALT-F4, Start Menu and so on...
Older Article
This article was published 13 years ago. Some information may be outdated or no longer applicable.
I wrote an article back in 2007 that’s still floating around the web in various discussions, including StackOverflow and DotNetSpider. I’ve decided to re-publish it. The article was relevant at the time, wasn’t tested on Windows 7 (because it didn’t exist yet), and comments are disabled on this post.
Before reading on: this article isn’t a call to create nasty applications. If you use this code, it should be for your own amusement or for learning purposes.
After researching how to disable key combinations, I found several ways to tackle the problem. The CTRL-ALT-DEL combo is part of the SAS (http://en.wikipedia.org/wiki/Secure_attention_keySecure Attention Sequence), so the “proper” solution is to write your own gina.dll (Graphical Identification and Authentication).
We won’t go there. Instead, here’s the workaround: we’ll use C#‘s Registry editing capabilities to set/change the group policy for the CTRL-ALT-DEL key sequence. Let’s see what this looks like without writing any code. Open Start Menu > Run and enter gpedit.msc. Navigate to: User Configuration > Administrative Templates > System > CTRL+ALT+DELETE Options. This is where you normally set the behaviour of that key combo. Select Remove Task Manager and double-click it.
Changing the value creates/modifies this registry entry: Software\Microsoft\Windows\CurrentVersion\Policies\System, and the value of DisableTaskMgr gets set to 1.
Task set. Let’s write the code.
Don’t miss this line:
using Microsoft.Win32;
Here’s the method:
public void KillCtrlAltDelete()
{
RegistryKey regkey;
string keyValueInt = "1";
string subKey = "Software\Microsoft\Windows\CurrentVersion\Policies\System";
try
{
regkey = Registry.CurrentUser.CreateSubKey(subKey);
regkey.SetValue("DisableTaskMgr", keyValueInt);
regkey.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
CTRL-ALT-DEL sorted. Now the rest. Here’s an easy one: disabling ALT+F4. Five lines:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
base.OnClosing(e);
}
For the remaining key combinations, I read through dozens of articles. I can’t name just one; at least 15 held useful bits. The code below uses the LowLevelKeyboardProc, which is:
The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function every time a new keyboard input event is about to be posted into a thread input queue. The keyboard input can come from the local keyboard driver or from calls to the keybd_event function. If the input comes from a call to keybd_event, the input was “injected”. However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
Don’t forget:
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Diagnostics;
Here’s the rest:
[DllImport("user32", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, int hMod, int dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int UnhookWindowsHookEx(int hHook);
public delegate int LowLevelKeyboardProcDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
[DllImport("user32", EntryPoint = "CallNextHookEx", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int CallNextHookEx(int hHook, int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);
public const int WH_KEYBOARD_LL = 13;
/*code needed to disable start menu*/
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public static int intLLKey;
public int LowLevelKeyboardProc(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)
{
bool blnEat = false;
switch (wParam)
{
case 256:
case 257:
case 260:
case 261:
//Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key,
blnEat = ((lParam.vkCode == 9) && (lParam.flags == 32)) | ((lParam.vkCode == 27) && (lParam.flags == 32)) | ((lParam.vkCode == 27) && (lParam.flags == 0)) | ((lParam.vkCode == 91) && (lParam.flags == 1)) | ((lParam.vkCode == 92) && (lParam.flags == 1)) | ((lParam.vkCode == 73) && (lParam.flags == 0));
break;
}
if (blnEat == true)
{
return 1;
}
else
{
return CallNextHookEx(0, nCode, wParam, ref lParam);
}
}
public void KillStartMenu()
{
int hwnd = FindWindow("Shell_TrayWnd", "");
ShowWindow(hwnd, SW_HIDE);
}
private void Form1_Load(object sender, EventArgs e)
{
intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0);
}
Quite obviously you can programmatically reset these values. Here's the code to re-enable everything:
public static void ShowStartMenu()
{
int hwnd = FindWindow("Shell_TrayWnd", "");
ShowWindow(hwnd, SW_SHOW);
}
public static void EnableCTRLALTDEL()
{
try
{
string subKey = "Software\Microsoft\Windows\CurrentVersion\Policies\System";
RegistryKey rk = Registry.CurrentUser;
RegistryKey sk1 = rk.OpenSubKey(subKey);
if (sk1 != null)
rk.DeleteSubKeyTree(subKey);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UnhookWindowsHookEx(intLLKey);
}
I hope you found some useful bits in here. I tried to pull together everything I found during my research on this topic.