I have some code here that is targeting windows event hooks in order to write to a log file when triggered. I am running this in powershell. I have successfully used this code to log mouse/keyboard events however when I use WH_CBT 5 using the CBTProc callback I receive no events. Even when using a mouse target of WH_MOUSE_LL 14 works just fine... can someone explain why? Have I missed something... or is it not possible for some reason?
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
Add-Type -TypeDefinition @"
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyLogger {
public static class Program {
private const int HOOK_CODE = 5;
private const int CALLBACK_CODE = 9;
private const string logPath = @"c:\MyTest.txt";
private const string logFileName = "log.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main() {
logFile = File.AppendText(logPath);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
UnhookWindowsHookEx(hookId);
}
private static IntPtr SetHook(HookProc hookProc) {
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(HOOK_CODE, hookProc, moduleHandle, 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
logFile.WriteLine("gg");
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
"@ -ReferencedAssemblies System.Windows.Forms
[MyLogger.Program]::Main();
Modded code
Add-Type -TypeDefinition @"
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyLogger {
public static class Program {
private const int WINEVENT_OUTOFCONTEXT = 0;
private const int EVENT_OBJECT_FOCUS = 0x8005;
private const string logPath = @"c:\MyTest.txt";
private const string logFileName = "log.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main() {
logFile = File.AppendText(logPath);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
}
private static IntPtr SetHook(HookProc hookProc) {
return SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, null, hookProc, 0, 0, WINEVENT_OUTOFCONTEXT);
}
private delegate IntPtr HookProc(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime);
private static IntPtr HookCallback(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime) {
logFile.WriteLine("gg");
}
internal enum SetWinEventHookFlags
{
WINEVENT_INCONTEXT = 4,
WINEVENT_OUTOFCONTEXT = 0,
WINEVENT_SKIPOWNPROCESS = 2,
WINEVENT_SKIPOWNTHREAD = 1
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, HookProc lpfnWinEventProc, int idProcess, int idThread, int dwflags);
private static extern int UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
"@ -ReferencedAssemblies System.Windows.Forms
[MyLogger.Program]::Main();
This code logs the HWND that has the focus.
Add-Type -TypeDefinition @"
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyLogger {
public static class Program {
private const int WINEVENT_OUTOFCONTEXT = 0;
private const int EVENT_OBJECT_FOCUS = 0x8005;
private const int WM_GETTEXT = 0x000D;
private const string logPath = @"c:\Temp\MyTest.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main() {
logFile = File.AppendText(logPath);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
}
private static IntPtr SetHook(HookProc hookProc) {
return SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, IntPtr.Zero, hookProc, 0, 0, WINEVENT_OUTOFCONTEXT);
}
private delegate void HookProc(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime);
private static void HookCallback(IntPtr hWinEventHook, int iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime) {
logFile.WriteLine(string.Format("{0}", hWnd));
}
internal enum SetWinEventHookFlags
{
WINEVENT_INCONTEXT = 4,
WINEVENT_OUTOFCONTEXT = 0,
WINEVENT_SKIPOWNPROCESS = 2,
WINEVENT_SKIPOWNTHREAD = 1
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, HookProc lpfnWinEventProc, int idProcess, int idThread, int dwflags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
}
}
"@ -ReferencedAssemblies System.Windows.Forms
[MyLogger.Program]::Main();
The hWnd passed to HookCallback can be a child window (like a list control or tree control, etc.), it is not always the outermost application window like you might be expecting from WH_CBT.
If you need the outermost application window, you can simply do something like:
HWND hwnd = hWndPassedToHookCallback;
HWND hwndApp;
do
{
hwndApp = hwnd;
hwnd = GetParent(hwnd)
} while(hwnd);
// hwndApp now is the outermost application window
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With