c#의 setwindowshookex
-
06-07-2019 - |
문제
화면에 그리기 위해 제 3 자 앱을 연결하려고합니다. 화면에 그리기가 쉽고 도움이 필요하지 않지만 사용에 문제가있는 것 같습니다. SetWindowsHookEx
다루다 WH_GETMESSAGE
. 마지막 두 매개 변수에 대해 무엇을 전달 해야하는지 알 수 없습니다.
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;
}
}
해결책
setwindowshookex 따라서 마지막 두 매개 변수를 세부 사항 :
hMod
LPFN 매개 변수가 가리키는 후크 절차를 포함하는 DLL에 대한 [in]. dwthreadid 매개 변수가 현재 프로세스에 의해 생성 된 스레드를 지정하고 후크 프로 시저가 현재 프로세스와 관련된 코드 내에있는 경우 hmod 매개 변수를 null로 설정해야합니다.
dwThreadId
in]은 후크 절차가 연관 될 스레드의 식별자를 지정합니다. 이 매개 변수가 0 인 경우 후크 절차는 호출 스레드와 동일한 데스크탑에서 실행되는 모든 기존 스레드와 관련됩니다.
필요한 방식으로 .NET DLL을 사용할 수는 없지만 확실히 시도 할 수 있습니다.
붙잡다 hMod
~을 통해 Marshal.gethinstance (typeof (form1). 모듈) 그리고 dwThreadId
~을 통해 프로세스. 스레드. 또는 설정하십시오 dwThreadId
글로벌 훅을 원한다면 0에서 0까지 (즉, 모두를위한 후크 GetMessage()
현재 데스크탑에서 호출) 그러나 성능 처벌을 조심하십시오.
다른 팁
나는 당신이 p/호출해야한다고 생각합니다 GetModuleHandle
그리고 세 번째 매개 변수에 대해 반환하는 핸들을 사용합니다. SetWindowsHookEx
. 나는 또한 믿는다 0
제 3 자 애플리케이션에서 특정 스레드를 연결하고 싶지 않기 때문에 네 번째 매개 변수에 맞습니다.
이것이 당신에게 효과가 없다면 SetWindowsHookEx
MSDN에서 올바른 방향을 가리킬 수 있습니다.
모르겠지만 API가 "다른 프로세스에 DLL을 주입"하는 것처럼 원하는 매개 변수 값을 사용하는 경우 관리되지 않은 DLL을 작성하는 경우에만 효과가있을 수 있습니다. 그것을 부를 수 있습니다.
나는 이것이 오래된 질문이라는 것을 알고 있지만 여전히 유용한 사람이 있기를 바라고 있습니다. 나는 당신이 섞이고 있다고 생각합니다 int
그리고 IntPtr
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
이 작업은 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
}
.NET 프레임 워크에서는 글로벌 후크가 지원되지 않습니다
wh_keyboard_ll 저급 후크 및 wh_mouse_ll 저급 후크를 제외하고 Microsoft .NET Framework에서 글로벌 후크를 구현할 수 없습니다.
글로벌 후크를 설치하려면 후크에는 유효하고 일관된 기능을 호출 해야하는 다른 프로세스에 자체적으로 DLL 내보내기가 있어야합니다. 이 동작에는 DLL 내보내기가 필요합니다.
.NET 프레임 워크는 DLL 내보내기를 지원하지 않습니다. 관리되는 코드는 함수 포인터에 대한 일관된 값의 개념이 없습니다. 이러한 기능 포인터는 동적으로 구축 된 프록시이기 때문입니다.
후크를 설치 한 스레드에서 낮은 수준의 후크 절차가 호출됩니다. 낮은 수준의 후크는 후크 절차를 DLL에서 구현할 필요가 없습니다.
또한보십시오:탐정 -WPF 스파이 유틸리티
또는 내 wpf => wf => win32 ll_keyboard 후크 프록시 w/ gestures