Question

J'essaie de connecter une application tierce afin de pouvoir afficher son écran. Dessiner à l'écran est facile et je n'ai besoin d'aucune aide, mais il semble que l'utilisation de SetWindowsHookEx me pose problème pour gérer WH_GETMESSAGE . Je ne vois pas quoi passer pour les deux derniers paramètres.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowDrawer
{
    public partial class Form1 : Form
    {
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static IntPtr hHook;
        IntPtr windowHandle;
        uint processHandle;

        HookProc PaintHookProcedure;     

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        // When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet =System.Runtime.InteropServices.CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        { 
            PaintHookProcedure = new HookProc(PaintHookProc);
            windowHandle = FindWindowByCaption(0, "Untitled - Notepad");
            uint threadID = GetWindowThreadProcessId(windowHandle, out processHandle);
            IntPtr hMod = System.Runtime.InteropServices.Marshal.GetHINSTANCE(typeof(Form1).Module);

            // HERE IS THE PROBLEM.  WHAT THE HECK DO I PASS INTO THE LAST 2 PARAMS?  I get a null pointer
            hHook = SetWindowsHookEx(WH_GETMESSAGE, PaintHookProcedure, hMod, threadID);
        }

        public int PaintHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
           // Do some painting here.
            return CallNextHookEx(hHook, nCode, wParam, lParam); 
        }

        private const int WM_PAINT = 15;
        private const int WH_GETMESSAGE = 3;
    }
}
Était-ce utile?

La solution

SetWindowsHookEx spécifie ainsi les deux derniers paramètres :

  • hMod
  

[in] Handle vers la DLL contenant le   procédure de hook pointée par le lpfn   paramètre. Le paramètre hMod doit être   mis à NULL si le dwThreadId   paramètre spécifie un thread créé   par le processus actuel et si le crochet   la procédure est dans le code   associé au processus en cours.

  • dwThreadId
  

[in] Spécifie l'identifiant du   fil avec lequel la procédure de crochet   est d'être associé. Si ce paramètre   est zéro, la procédure de hook est   associé à tous les threads existants   fonctionnant sur le même bureau que le   fil d'appel.

Je ne suis pas sûr que vous puissiez utiliser une DLL .NET de la manière requise, mais vous pouvez certainement essayer.

Récupérez hMod via Marshal.GetHINSTANCE (typeof (Form1) .Module) et dwThreadId via Process.Threads . Vous pouvez également définir dwThreadId sur 0 si vous souhaitez un raccordement global (c'est-à-dire un raccordement pour tous les appels GetMessage () dans le bureau actuel), mais prenez garde aux pénalités de performances. / p>

Autres conseils

Ce qui suit suggère que cela ne fonctionnera pas:

  

"Les raccords globaux ne sont pas pris en charge dans le .NET Framework. À l'exception des points d'ancrage de bas niveau WH_KEYBOARD_LL et WH_MOUSE_LL, vous ne pouvez pas implémenter de points d'ancrage globaux dans Microsoft .NET Framework. "

De "Comment définir un point d'ancrage Windows dans Visual C # .NET"

Je pense que vous devez P / Invoke < code> GetModuleHandle et utilisez le descripteur qu'il renvoie pour le troisième paramètre de SetWindowsHookEx . Je pense également que 0 est correct pour le quatrième paramètre, car vous ne souhaitez pas accrocher un thread spécifique dans l'application tierce.

Si cela ne vous convient pas, SetWindowsHookEx sur MSDN peut vous orienter dans la bonne direction.

Je ne sais pas, mais si vous utilisez des valeurs de paramètre qui spécifient ce que vous souhaitez, comme le dit l'API, "injecter une DLL dans un autre processus", alors, je sais que cela ne fonctionnera que si vous écrire une DLL non gérée à partir de laquelle l'appeler.

Je sais qu’il s’agit d’une question ancienne, mais j’espère qu’il restera encore quelqu'un qui trouvera cela utile. Je pense que vous mélangez int et IntPtr

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

Ce travail pour moi utilise 13 ...

 private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(13, proc,
                GetModuleHandle(curModule.ModuleName), 0);
            }
        }
  internal enum HookType : uint {
    WH_JOURNALRECORD = 0,
    WH_JOURNALPLAYBACK = 1,
    WH_KEYBOARD = 2,
    WH_GETMESSAGE = 3,
    WH_CALLWNDPROC = 4,
    WH_CBT = 5,
    WH_SYSMSGFILTER = 6,
    WH_MOUSE = 7,
    WH_HARDWARE = 8,
    WH_DEBUG = 9,
    WH_SHELL = 10,
    WH_FOREGROUNDIDLE = 11,
    WH_CALLWNDPROCRET = 12,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
  }

Les points d'ancrage globaux ne sont pas pris en charge dans le .NET Framework

Sauf pour le hook de bas niveau WH_KEYBOARD_LL et le hook de bas niveau WH_MOUSE_LL, vous ne pouvez pas implémenter de hooks globaux dans Microsoft .NET Framework.

Pour installer un hook global, un hook doit avoir une exportation de DLL native pour s'injecter dans un autre processus nécessitant une fonction cohérente valide à appeler. Ce comportement nécessite une exportation DLL.

.NET Framework ne prend pas en charge les exportations de DLL. Le code géré n'a pas de concept de valeur cohérente pour un pointeur de fonction, car ces pointeurs de fonction sont des mandataires construits de manière dynamique.

Les procédures de hook de bas niveau sont appelées sur le thread qui a installé le hook. Les hooks de bas niveau ne nécessitent pas que la procédure de hook soit implémentée dans une DLL.

Voir aussi: Snoop - L'utilitaire d'espionnage WPF

Ou mon WPF = > WF = > Proxy-crochet Win32 LL_Keyboard avec gestes

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top