Frage

Ich versuche, einen 3rd-Party-App Haken, so dass ich auf seinen Bildschirm zu zeichnen. Zeichnung auf dem Bildschirm ist einfach, und ich brauche keine Hilfe mit ihm, aber ich zu sein scheinen Probleme mit mit der Verwendung von SetWindowsHookEx WH_GETMESSAGE zu behandeln. Ich kann nicht herausfinden, was in den letzten beiden Parameter zu übergeben.

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;
    }
}
War es hilfreich?

Lösung

SetWindowsHookEx Spezifika die beiden letzten Parameter thusly :

  • hMod
  

[in] an die DLL Handle die enthält   Hookprozedur auf den durch den lpfn   Parameter. Der hMod Parameter muss sein   auf NULL gesetzt, wenn der dwThreadId   Parameter gibt einen Thread erstellt   durch den aktuellen Prozess, und wenn der Haken   Verfahren ist innerhalb des Codes   im Zusammenhang mit dem aktuellen Prozess.

  • dwThreadId
  

[in] Gibt die Kennung des   Gewinde, mit dem das Verfahren hook   assoziiert ist. Wenn diese Parameter   die Hookprozedur Null ist, ist   mit allen bestehenden Fäden zugeordnet   in demselben Desktop wie der Lauf   Aufruf-Thread.

Ich bin nicht sicher, ob Sie einen .NET-DLL in der Art und Weise verwenden können, erforderlich, aber man kann auf jeden Fall versuchen.

Schnappen hMod über Marshal.GetHINSTANCE (typeof (Form1) .module) und dwThreadId über Process.Threads . Alternativ setzen dwThreadId auf 0, wenn Sie einen globalen Haken wollen (dh. Ein Haken für alle GetMessage() Anrufe in der aktuellen Desktop), aber hüte dich vor den Leistungseinbußen.

Andere Tipps

Im Folgenden legt nahe, das wird nicht funktionieren:

  

"Globale Haken sind nicht im .NET Framework unterstützt. Mit Ausnahme des WH_KEYBOARD_LL Low-Level-Haken und dem WH_MOUSE_LL Low-Level-Haken, man kann nicht global Haken in dem Microsoft .NET Framework implementieren."

"Wie ein Windows-Haken in Visual C # .NET, um"

Ich glaube, Sie zu P benötigen / Invoke GetModuleHandle und mit dem Griff es für den dritten Parameter von SetWindowsHookEx zurückgibt. Ich glaube auch, 0 für den vierten Parameter korrekt ist, wie Sie wollen nicht irgendeinen bestimmten Thread in der Anwendung von Drittanbietern anschließen.

Wenn dies nicht für Sie arbeiten, SetWindowsHookEx auf MSDN können Sie in die richtige Richtung zeigen.

Ich weiß nicht, aber wenn Sie Parameterwerte verwenden, die angeben, dass Sie möchten, wie die API sagt hilft, „eine DLL in einem anderen Prozess injizieren“, dann für alle weiß, dass ich es kann nur funktionieren, wenn Sie schreiben eine nicht verwaltete DLL aus dem sie nennen.

Ich weiß, dass dies ist eine alte Frage, aber ich bin der Hoffnung, dass es noch jemanden gibt, der dies nützlich finden. Ich denke, dass Sie vermischen int und IntPtr

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

Diese Arbeit für mich 13 verwenden ...

 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
  }

Globale Haken sind nicht im .NET Framework unterstützt

Mit Ausnahme des WH_KEYBOARD_LL Low-Level-Haken und dem WH_MOUSE_LL Low-Level-Haken, man kann nicht global Haken in dem Microsoft .NET Framework implementieren.

Um einen globalen Hook zu installieren, muss ein Haken hat einen native DLL Export selbst in einem anderen Prozess zu injizieren, die eine gültige, konsistente Funktion erfordert ins Leben zu rufen. Dieses Verhalten erfordert eine DLL zu exportieren.

Das .NET Framework nicht DLL Exporte unterstützen. Managed Code hat kein Konzept für einen konsistenten Wert für einen Funktionszeiger, da diese Funktionszeiger sind Proxies, die dynamisch erstellt werden.

Low-Level-Hook-Prozeduren werden auf dem Thread aufgerufen, die den Hook installiert. Low-Level-Haken nicht verlangen, dass die Hook-Prozedur in einem DLL implementiert werden.

Siehe auch: Snoop - Die WPF Spy Dienstprogramm

oder meine WPF => WF => Win32 LL_Keyboard Proxy Haken w / Gestures

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top