MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как установить низкоуровневый хук на отдельный процесс?"
Answer 946370
Возможности установить низкоуровневый хук на отдельный процесс нет. Низкоуровневый хук потому и назван "низкоуровневым", что он вызывается до того, как событие ввода доходит до целевого процесса (точнее потока, так как очереди сообщений принадлежат потокам). Несмотря на то, что функция SetWindowsHookEx позволяет передать четвертым параметром ID потока для установки хука только на события этого потока, для WH_KEYBOARD_LL этот параметр не работает, похоже, именно из-за его особой природы.
Однако, в какой именно процесс будет отправлено сообщение, в общем, не секрет: это процесс, владеющий текущим активным окном. Это значит, что реализовать фильтрацию событий хука определенного процесса можно довольно просто с использованием функций GetWindowThreadProcessId и GetForegroundWindow. Переработав пример отсюда, получаем такой код:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Process[] prs = Process.GetProcessesByName("notepad"); if (prs.Length == 0) throw new ApplicationException("Process not found!"); KeyLogger.SetHook((uint)prs[0].Id); } } class KeyLogger { const int WH_KEYBOARD_LL = 13; const int HC_ACTION = 0; const int WM_KEYDOWN = 0x0100; const uint VK_CAPITAL = 0x14; static uint hookProcessID; static IntPtr hookID; static KeyboardProc Callback = KeyboardHookCallback; public static void SetHook(uint pid) { hookProcessID = pid; hookID = SetWindowsHookEx(WH_KEYBOARD_LL, Callback, IntPtr.Zero, 0); if (hookID == IntPtr.Zero) throw new ApplicationException("Failed to install hook!"); Console.WriteLine("Started listening keyboard events..."); Application.Run(); } static IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int vkCode = Marshal.ReadInt32(lParam); uint pid = 0; GetWindowThreadProcessId(GetForegroundWindow(), out pid); if (pid == hookProcessID) { Console.Out.WriteLine("Key: " + ((Keys)vkCode).ToString() + ";"); } } return CallNextHookEx(hookID, nCode, wParam, lParam); } delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hInstance, int threadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); } }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.