SetWindowsHookEx创建一个本地钩子。如何使其全球化? [英] SetWindowsHookEx creates a local hook. How to make it global?

查看:202
本文介绍了SetWindowsHookEx创建一个本地钩子。如何使其全球化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi XE应用程序中,我试图设置一个全局钩子来监视焦点更改。钩子在dll中创建:

In a Delphi XE application I am trying to set up a global hook to monitor focus changes. The hook is created in a dll:

focusHook := SetWindowsHookEx( WH_CBT, @FocusHookProc, HInstance, 0 );
// dwThreadId (the last argument) set to 0 should create a global hook

相同的dll我有挂钩过程向主机应用程序窗口发送消息:

In the same dll I have the hook procedure that posts a message to the host app window:

function FocusHookProc( code : integer; wParam: WPARAM; lParam: LPARAM ) : LResult; stdcall;
begin
  if ( code < 0 ) then
  begin
    result := CallNextHookEx( focusHook, code, wParam, lParam );
    exit;
  end;

  result := 0;

  if ( code = HCBT_SETFOCUS ) then
  begin
    if ( hostHWND <> INVALID_HANDLE_VALUE ) then
      PostMessage( hostHWND, cFOCUSMSGID, wParam, lParam );
  end;
end;

这是有效的,但主机只接收应用程序本身的焦点更改通知。主窗体上有一个备忘录和几个TButtons,它们之间的切换会产生预期的消息。然而,应用程序本身之外的任何焦点更改都不会报告。

This works, but the host only receives notifications on focus changes within the application itself. There is a memo and a few TButtons on the main form, and switching focus between them produces the expected message. However, any focus changes outside the application itself are never reported.

我想这与DLL注入其他进程的多个实例有关。有一个类似的问题,接受回覆这里,但它是为C,我不能相当看看我如何在Delphi中执行相同的操作(例如,用于设置共享内存的pragma语句)。

I suppose it has something to do with multiple instances of the DLL getting injected into other processes. There is a similar question with an accepted reply here, but it is for C, and I can't quite see how I can do the same in a Delphi dll (e.g. the pragma statements to set up shared memory).

(这主要是一个概念证明,但我仍然希望让它工作,我需要知道在我的应用程序通过点击Alt + Tab,激活热键等激活之前,哪个窗口是活动的。问题是如果鼠标或alt +标签被使用,GetForegroundWindow总是返回我自己的应用程序的窗口句柄,无论我早就把它,如通过挂钩应用程序的主要消息队列,所以钩子似乎是唯一可行的解​​决方案,虽然我不太喜欢这个想法。)

推荐答案

由于DLL被注入到另一个进程中,所以你不是要获得任何除了你被盗的过程以外的任何断点拥抱另外,其他进程中的每个DLL的实例也会获得自己的全局/静态数据。如果hostHWND是全局的,那么在其他进程中它的值与此不同。实际上甚至不会被初始化。您需要使用共享内存块来共享进程之间的值。可能需要使用共享互斥体和其他同步对象来确保共享内存写入受到保护。最后,如果您使用的是Windows Vista +,只有具有相同访问级别和更低级别的进程才能注册该DLL。 IOW,如果您正在以已登录的用户身份运行该进程,则仅以已登录的用户身份进行处理,才能注销该DLL。

Since the DLL is injected into another process, you're not going to get any breakpoints hit for anything other than the process you're debugging. Also, each instance of the DLL in the other process also get their own global/static data. If hostHWND is a global, it won't be the same value in the other process as it is in this one. In fact it won't even get initialized. You need to use a shared memory block to share values among the processes. Shared mutexes and other synchronization objects may need to be used to ensure any shared memory writes are protected. Finally, if you're using Windows Vista+, only processes with the same access level and below will get the DLL injected. IOW, if you're running the process as the logged-in user, only processed running as the logged-in user will get that DLL injected.

这篇关于SetWindowsHookEx创建一个本地钩子。如何使其全球化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆