📜 ⬆️ ⬇️

Disable ctrl-alt-delete, alt-tab, Start, and other combinations

This is a free translation of an article from the tamas.io website about programmatically disabling and enabling Windows hotkeys using C #. Most recently, I myself needed similar functions in my program, and I was surprised to find that there was nothing about it on Runet, and indeed, very little was said about it on the network. So, if it is interesting or also necessary, as it was to me - welcome!

I wrote this article in 2007 and it still goes around the network and is mentioned in various discussions, including StackOverflow and DotNetSpider , so I decided to publish it again. It was already relevant then and was not tested on Windows 7, due to the fact that at that time it simply did not exist physically.
Before you continue reading, please note that this article does not encourage you to create malicious applications. You can use this code for educational purposes or for entertainment.

After a little research into disabling keys and their combinations, I learned that there are several ways to change the behavior of the previously mentioned key combos.

Do not worry, we will not consider them here, but I will show you how to work with them.
')
We use the C # registry editing features to set / change the group policy for the key sequence CTRL-ALT-DEL. Let's see what can be done without writing a single line of code. Open “Start -> Run” and type gpedit.msc. Go to: User Configuration> Administrative Templates> System> Options after pressing CTRL-ALT-DEL (User Configuration> Administrative Templates> System> CTRL + ALT + DELETE Options). This is the place where in the standard way you can set the action that will be triggered by pressing this combo. Double-click on “Remove Task Manager”. Changing this parameter changes the value in Software \ Microsoft \ Windows \ CurrentVersion \ Policies \ System and the value of DisableTaskMgr will be 1.

Now the task has become clearer.

Important, do not miss this line:

using Microsoft.Win32; 


The method I wrote looks like this:

 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()); } } 


Thus, we took care of changing the value of the CTRL-ALT-DEL combination. Consider the remaining combinations. You may have found it difficult, but it’s easier than that. How to disable ALT + F4? Only 5 lines of code:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = true; base.OnClosing(e); } 


Good. I had to read a lot about the rest and now it will be difficult to name exactly those articles that helped me figure it out, but out of all there were 15 pieces that contained at least some useful information. I'll give you a method called hook. The code snippet uses LowLevelKeyboardProc, which:

The LowLevelKeyboardProc procedure is a program-defined or library-specific function call procedure used in conjunction with the SetWindowsHookEx function. The system calls this function each time a keyboard input event is about to be placed in the input stream queue. Keyboard input can pass through a driver or through calls to the keybdevent function. If the call came through a keybdevent call, then it was “injected”. However, the WHKEYBOARDLL hook is not embedded in another process. Instead, the context switches to another process on which the hook is installed and is called in its original form. Then, the context switches back to the application that triggered the event.


And again, do not forget:

 using System.Runtime.InteropServices; using System.Security.Principal; using System.Diagnostics; 


Here everything else that may still be useful to you:

 [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); } 

It is obvious that you can programmatically return all values ​​by re-enabling all combinations:
 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 enjoyed the article and found something useful in it. I tried to collect here all the information that I could find on this topic.

From myself I will add that in .NET4 code of the form:

 intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(), 0); 


Does not work. You need to write something like:

 var inst = LoadLibrary("user32.dll").ToInt32(); intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, inst, 0); 


Well, in the beginning of the AddHooks structure code, among other things, import to do:

 LoadLibrary: [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr LoadLibrary(string lpFileName); 


I hope the translation is not quite bad and will be useful to someone.
UPD: Link to the complete work program.

Source: https://habr.com/ru/post/206480/


All Articles