Bloquer les touches Windows, Atl+tab, ... [Résolu]

NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 23 mai 2017 à 09:57 - Dernière réponse : Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention
- 6 juin 2017 à 10:53
Bonjour,

Dans le cadre d'une application que je développe, je dois bloquer les touches systèmes (Windows, Atl+Tab, ...) afin d'éviter que l'utilisateur ne contourne l'application.

Actuellement, j'ai essayé plusieurs méthodes, mais aucun succès.

il y a 2 méthodes principales que j'ai essayé :

Modification du registre :
HKeyLocalMachine\System\CurrentControlSet\Control\Keyboard Layout
Scancode Map={ 00, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 00, 00, 00, 0x5B, 0xE0, 00, 00, 0x5C, 0xE0, 00, 00, 00, 00 }

Et l'utilisation des bibliothèques de Hook :
    [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int UnhookWindowsHookEx(int hHook);
    [DllImport("user32", EntryPoint = "SetWindowsHookExA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]

    public static extern int SetWindowsHookEx(int idHook, KeyboardHookDelegate lpfn, int hmod, int dwThreadId);
    [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]

    private static extern int GetAsyncKeyState(int vKey);
    [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]

(Code converti de VB à C# en provenance de http://www.dreamincode.net/forums/topic/99611-disable-a-key/ )

Mais à chaque fois, tout semble s'être bien déroulé, mais les touches fonctionnent quand même.

Aurais-je raté quelque chose ?

VS.NET 2013, .NET 4.5, Win 7 Pro
Afficher la suite 

17 réponses

Répondre au sujet
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 23 mai 2017 à 19:31
0
Utile
3
Salut,

as tu essayé un hook en C#.
J'ai vu celui-là
http://codes-sources.commentcamarche.net/source/view/50696/1204446

NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 23 mai 2017 à 19:48
J'avais essayé un code similaire (importé et adapté d'un autre projet en VB6), sans succès, mais dès Mercredi (31), j'essayerai ta suggestion. (J'ai pas de Windows à la maison, que du Linux)
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 23 mai 2017 à 19:55
Grand week end!
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 23 mai 2017 à 20:29
Quand ta boite t'oblige à solder tes congés avant fin Mai, et qu'un pont se présente, tu le change en viaduc :D
Commenter la réponse de Whismeril
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 24 mai 2017 à 20:50
0
Utile
2
J'ai pris le temps de tester le code.
Il est configuré pour bloquer toutes les touches du clavier, tant que l'appli tourne tu ne peux plus rien faire sur le pc, à priori, même pas ctrl alt suppr. Je dis à priori car sur le clavier mac court, y'a pas de touche suppr et j'ai essayé avec le clavier visuel de W7.

Le hic c'est que je n'arrive pas exécuter en pas à pas dans le projet d'origine, y a un problème de configuration de symbole (ça a pourtant l'air correct), et quand je fais un nouveau projet, le hook ne marche pas....
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 24 mai 2017 à 21:50
Ah, ça explique peut être pourquoi j'ai des soucis si le hook ne fonctionne pas ...
Merci pour le complément, je garde l'URL en fichier pour tester au boulot.
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 24 mai 2017 à 22:05
je continue à gratter
Commenter la réponse de Whismeril
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 25 mai 2017 à 12:18
0
Utile
7
Salut

j'ai trouvé, enfin j'ai bloquéça marche dans une virtual box sur Mac.
A partir de ce code (la version 2)

J'ai modifié la méthode KeyboardHookProc comme suit
        private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            //indicates if any of underlaing events set e.Handled flag
            bool handled = false;

            if (nCode >= 0)
            {
                //read structure KeyboardHookStruct at lParam
                KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

                //Ligne dépacée pour être valable sur tout le if, y'avait la même dans le  if (s_KeyUp != null && que j'ai supprimé
                Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;

                //raise KeyDown
                if (s_KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                {
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    s_KeyDown.Invoke(null, e);
                    handled = e.Handled;
                }

                // raise KeyPress
                if (s_KeyPress != null && wParam == WM_KEYDOWN)
                {
                    bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
                    bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

                    byte[] keyState = new byte[256];
                    GetKeyboardState(keyState);
                    byte[] inBuffer = new byte[2];
                    if (ToAscii(MyKeyboardHookStruct.VirtualKeyCode,
                              MyKeyboardHookStruct.ScanCode,
                              keyState,
                              inBuffer,
                              MyKeyboardHookStruct.Flags) == 1)
                    {
                        char key = (char)inBuffer[0];
                        if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
                        KeyPressEventArgs e = new KeyPressEventArgs(key);
                        s_KeyPress.Invoke(null, e);
                        handled = handled || e.Handled;
                    }
                }

                // raise KeyUp
                if (s_KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
                {
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    s_KeyUp.Invoke(null, e);
                    handled = handled || e.Handled;
                }

                switch (keyData)
                {
                    case Keys.Escape://esc
                        handled =  GetKeyState(VK_CONTROL) != 0;//si Ctrl est enfoncé
                        break;

                    case (Keys)92://Windows? sur mon mac c'est la touche "commande" alors je ne suis pas sûr
                        handled = true;
                        break;

                    case Keys.Tab://tab
                        //handled = wParam == WM_SYSKEYDOWN;//si Alt est enfoncé, option 1
                        handled = GetKeyState(VK_MENU) != 0;//opion 2
                        break;

                    case Keys.Delete://suppr
                        handled = wParam == WM_SYSKEYDOWN && GetKeyState(VK_CONTROL) != 0;//si Ctrl et Alt sont enfoncés, j'ai pas la touche suppr sur mon clavier, donc pas testé
                        break;
                }
            }



            //if event handled in application do not handoff to other listeners
            if (handled)
                return -1;

            //forward to other application
            return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
        }



J'ai déplacé la définition de keyData pour le rendre global à la boucle if(nCode >= 0), j'ai mis un commentaire, et ajouté un swicth à la fin du if.

Il faut aussi ajouter les constantes
        private const byte VK_CONTROL = 0x11;
        private const byte VK_MENU = 0x12;//Alt
dans HookManager.Windows.cs
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention > NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 31 mai 2017 à 16:38
En rentrant, je te mets tout sur cijoint
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention > Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 31 mai 2017 à 16:47
Merci, après quelques essais, j'ai enfin compris ce qui posait problème ...
Quand un site est pas très bien conçu, il regarde le referer pour voir quel fichier il faut télécharger et si tu as configuré ton navigateur pour ne jamais envoyé le Referer (vie privée, traçage & co), ben forcément, ça fonctionne moins bien ...
Finalement, j'ai dl le zip, je vais regarder comment faire.
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention > NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 31 mai 2017 à 17:18
Ha ben je venais de le mettre sur cijoint
http://www.cjoint.com/c/GEFpr2daYNs

Y'a mes modifs, le lien est actif 4 jours.
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 1 juin 2017 à 09:53
Merci, ça fonctionne, j'ai juste ajouté une modification dans le code de KeyboardHookProc :
                //raise KeyDown
                if (s_KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                {
                    var lModifier = Keys.None;
                    lModifier |= ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? Keys.Shift : Keys.None);
                    lModifier |= ((GetKeyState(VK_CONTROL) & 0x80) == 0x80 ? Keys.Control : Keys.None);
                    lModifier |= ((GetKeyState(VK_MENU) & 0x80) == 0x80 ? Keys.Alt : Keys.None);

                    KeyEventArgs e = new KeyEventArgs(keyData | lModifier);
                    s_KeyDown.Invoke(null, e);
                    handled = e.Handled;
                }

Cela permet d'avoir les modificateurs(Ctrl, Alt, Shift) sur le KeyDown (je n'ai pas fais les autres car je n'en ai pas besoin).
Afin d'intercepter les Alt+F4, ...

J'ai modifié la gestion de l'event KeyDown de TestFormStatic :
        private void HookManager_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.RWin:
                case Keys.LWin:
                case Keys.Apps:
                    e.Handled = true;
                    break;
                case Keys.F4:
                    if ((e.Modifiers & Keys.Alt) != 0)
                        e.Handled = true;
                    break;
                case Keys.Delete:
                    if ((e.Modifiers & (Keys.Alt | Keys.Control)) != 0)
                        e.Handled = true;
                    break;
            }
            textBoxLog.AppendText(string.Format("KeyDown - {0} - {1} - {2}\n", e.KeyCode, e.Modifiers, e.Handled));
            textBoxLog.ScrollToCaret();
        }


Et pour info, le Ctlr+Alt+Del passe quand même, il n'est pas bloquable (mais on le voit passer).

Je vais mettre tout ça dans mon projet final et je test le tout.
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 1 juin 2017 à 11:08
Je continue mes retours.

Dans la fonction EnsureSubscribedToGlobalKeyboardEvents
J'ai du remplacer un peu le code du hook, car je suis en .NET4.5 et ça ne passait pas :
                s_KeyboardHookHandle = SetWindowsHookEx(
                    WH_KEYBOARD_LL,
                    s_KeyboardDelegate,
                    LoadLibrary("user32.dll"),
                    0);

Et ajouter dans le fichier HookManager.Windows.cs :
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr LoadLibrary(string lpFileName);


Maintenant, j'ai une erreur 1404 lors de la libération du hook (dans ForceUnsunscribeFromGlobalKeyboardEvents), mais cela ne pose pas trop de souci à Windows, donc, j'ignore cette erreur pour le moment.
Commenter la réponse de Whismeril
NHenry 14002 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 12 décembre 2017 Dernière intervention - 6 juin 2017 à 09:14
Whismeril 10526 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 13 décembre 2017 Dernière intervention - 6 juin 2017 à 10:53
Salut,
super
Commenter la réponse de NHenry

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.