2009-11-28 6 views
10

Ich versuche, eine 3rd Party App zu haken, so dass ich auf den Bildschirm zeichnen kann. Das Zeichnen auf den Bildschirm ist einfach und ich brauche keine Hilfe damit, aber ich habe Probleme mit der Verwendung von SetWindowsHookEx, um WH_GETMESSAGE zu behandeln. Ich kann nicht herausfinden, was ich für die letzten 2 Parameter weitergeben soll.SetWindowsHookEx in C#

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





} 

Antwort

12

SetWindowsHookEx Spezifika die beiden letzten Parameter thusly:

  • hMod

[in] an die DLL Handle der Hookprozedur auf den durch den lpfn Parameter enthält. Der Parameter hMod muss auf NULL gesetzt sein, wenn der Parameter dwThreadId einen durch den aktuellen Prozess erstellten Thread angibt und wenn die Prozedur hook innerhalb des Codes liegt, der dem aktuellen Prozess zugeordnet ist.

  • dwThreadId

[in] Gibt die Kennung des Gewinde, mit dem das Hookprozedur zugeordnet werden. Wenn dieser Parameter Null ist, ist die Hookprozedur mit allen bestehenden Fäden zugeordnet in der gleichen Desktop als aufrufenden Thread ausgeführt wird.

Ich bin mir nicht sicher, ob Sie eine .NET-DLL in der erforderlichen Weise verwenden können, aber Sie können es auf jeden Fall versuchen.

Ergreifen Sie hMod über Marshal.GetHINSTANCE(typeof(Form1).Module) und dwThreadId über Process.Threads. Alternativ können Sie dwThreadId auf 0 setzen, wenn Sie einen globalen Hook (dh einen Hook für alle GetMessage() Anrufe im aktuellen Desktop) wünschen, aber achten Sie auf die Leistungseinbußen.

+0

ich den Code oben modded widerzuspiegeln Ihre Idee: Ich bekomme immer noch SetWindowsHookEx (WH_GETMESSAGE, PaintHookProcedure, HMod, threadID) == 0; – Darthg8r

+1

Es gibt die eindeutige Möglichkeit, dass Sie Ihre PaintHookProcedure in einer separaten DLL packen müssen; was die Verwendung von .NET ausschließt. Ergreifen Sie den Fehlermeldungscode mit GetLastError(), und sehen Sie, was das Problem ist. –

+2

Und von GetLastError() meine ich Marshal.GetLastWin32Error(); p/Aufruf von GetLastError() direkt ist unzuverlässig. –

2

Ich glaube, Sie zu P brauchen/Invoke GetModuleHandle und mit dem Griff es für den dritten Parameter von SetWindowsHookEx zurückgibt. Ich glaube auch, dass 0 für den vierten Parameter korrekt ist, da Sie keinen bestimmten Thread in der Drittanbieteranwendung haken möchten.

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

+0

GetModuleHandle (string lpModuleName);? Was passiere ich in sie die eXE-Name – Darthg8r

+0

Pass 'NULL' und es wird der Griff von dem rufenden Prozess (. ausführbare Datei) ziehen –

3

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ß ich es, wenn Sie nur funktionieren könnte Schreiben Sie eine nicht verwaltete DLL, von der sie aufgerufen werden soll.

2

Ich weiß, dass dies eine alte Frage ist, aber ich hoffe, dass es noch jemanden gibt, der das nützlich finden wird. 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); 
7

Nachfolgend schlägt vor, das wird nicht funktionieren:

„Globale Haken sind nicht in der unterstützt.NET Framework. Mit Ausnahme des WH_KEYBOARD_LL Low-Level-Haken und dem WH_MOUSE_LL Low-Level-Haken, können Sie nicht globalen Haken in dem Microsoft .NET Framework implementieren.“

Von "How to set a Windows hook in Visual C# .NET"

-1

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