2015-05-07 4 views
1

У меня есть код здесь, который нацеливается на крючки событий Windows, чтобы записывать в файл журнала при запуске. Я запускаю это в powershell. Я успешно использовал этот код для регистрации событий мыши/клавиатуры, однако, когда я использую WH_CBT 5 с использованием обратного вызова CBTProc, я не получаю никаких событий. Даже при использовании мышиной цели WH_MOUSE_LL 14 работает отлично ... может кто-нибудь объяснить, почему? Я что-то пропустил ... или по какой-то причине это невозможно?Обратный вызов CBTProc не работает, setEventHookEx

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 код

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(); 
+0

Не знаю, как вы намерены внедрить в другие процессы с кодом .net. Также возникает вопрос, почему вы решили пренебречь проверкой ошибок. –

ответ

2

Этот код регистрирует HWND с фокусом.

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 передается HookCallback может быть дочерним окном (как элемент управления списка или дерева контроля и т.д.), это не всегда внешний окно приложения, как вы могли бы ожидать от WH_CBT.

Если вам нужно самое наружное окно приложения, вы можете просто сделать что-то вроде:

HWND hwnd = hWndPassedToHookCallback; 
HWND hwndApp; 
do 
{ 
    hwndApp = hwnd; 
    hwnd = GetParent(hwnd) 
} while(hwnd); 

// hwndApp now is the outermost application window 
+0

Большое спасибо – elev8ed

0

В отличие от WH_MOUSE_LL, обратный вызов для WH_CBT должен быть в процессе, который подключен; поэтому обратный вызов должен быть в DLL.

+0

Хммм, хорошо, так или иначе, чтобы вызвать обратный вызов в любое время, когда окно набирает фокус? Спасибо – elev8ed

+0

@Ben - Так как ваш код находится в PowerShell, кажется, вам нужен крючок, который поддерживает обратные вызовы процессов. К счастью, [SetWinEventHook] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx) подходит для счета: 'SetWinEventHook (EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS , NULL, MyFocusHookProc, 0, 0, WINEVENT_OUTOFCONTEXT); ' –

+0

Спасибо. Я добавил модифицированную версию кода. Мой опыт здесь слабый, поэтому, если вы можете указать мне в правильном направлении с моей модифицированной версией, это было бы здорово. Я получаю различные ошибки, которые я не могу определить. Большое спасибо за Вашу помощь. – elev8ed

Смежные вопросы