c# - CBTProc 回调不起作用,setEventHookEx

标签 c# winforms powershell winapi

我这里有一些代码针对 Windows 事件 Hook ,以便在触发时写入日志文件。我在 powershell 中运行它。我已成功使用此代码记录鼠标/键盘事件,但是当我使用 CBTProc 回调使用 WH_CBT 5 时,我没有收到任何事件。即使使用 WH_MOUSE_LL 14 的鼠标目标也能正常工作......有人可以解释为什么吗?我是否遗漏了什么...或者由于某种原因不可能?

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

修改后的代码

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

最佳答案

此代码记录具有焦点的 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();

传递给HookCallbackhWnd可以是子窗口(比如列表控件或者树控件等),不一定像你一样是最外层的应用程序窗口可能期待 WH_CBT。

如果你需要最外面的应用程序窗口,你可以简单地做这样的事情:

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

// hwndApp now is the outermost application window

关于c# - CBTProc 回调不起作用,setEventHookEx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30113314/

相关文章:

xml - 设置RestartOnFailure后无法在Powershell中导入计划任务xml

c# - 如果条件取决于另一个变量,如何在不同的条件之间进行选择

c# - 如何检查类的属性是否抛出异常

c# - 如何更改列表框中项目的名称/字符串?

powershell - Azure Service Fabric - 提高本地性能

PowerShell 函数 $ 输入参数

c# - 如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?

C# Regex.Match 花括号 - 仅内容? (不包括大括号)

C# ToolStrip 标签有时会先打印最后一个字符

.net - 如何在 PropertyGrid 中为模态 UITypeEditor 重新标记省略号按钮?