我需要做些什么来使我的WH_SHELL或WH_CBT挂钩程序从其他进程接收事件?

我需要做些什么来使我的WH_SHELL或WH_CBT挂钩程序从其他进程接收事件?,第1张

概述我需要做些什么来使我的WH_SHELL或WH_CBT挂钩程序从其他进程接收事件?

我试图使用SetwindowsHookEx来build立一个WH_SHELL挂钩来获得系统范围的HSHELL_WINDOWCREATED和HSHELL_WINDOWDESTROYED事件的通知。 我把0传递给最后一个DWThreadID参数,根据文档 , 这个参数应该“将钩子过程与调用线程在同一桌面上运行的所有现有线程相关联”。 我也传递了我的DLL( HInstance在Delphi中)的句柄hMod参数,我所看到的所有例子。

然而,我只能得到我自己的应用程序创build的窗口的通知,而且往往会导致桌面进程一旦closures我的应用程序就会熄灭。 在你问之前,我打电话给UnhookwindowsHookEx 。 我也总是从我的处理程序中调用CallNextHookEx 。

我从一个有限的用户帐户运行我的testing应用程序,但到目前为止,我还没有发现任何暗示,这将发挥作用…(虽然这实际上令我惊讶)

AFAICT,我做了所有的书(显然我没有,但到目前为止,我不知道在哪里)。

Win32,如何在编译的程序中使用C ++挂钩函数?

如果鼠标和触摸板都启用,如何检测input设备

64位DLL入口点覆盖

在64位windows中挂钩32位进程

在挂接WH_CALLWNDPROC之后没有得到Window Procedure消息

我正在使用delphi(2007年),但这应该不是真的,我想。

编辑:也许我应该提到这之前:我下载并尝试了几个例子(虽然不幸的是没有那么多的delphi – 特别是没有WH_SHELL或WH_CBT )。 虽然他们不会像我的testing应用程序那样崩溃系统,但是他们仍然不会捕获来自其他进程的事件(尽pipe我可以使用ProcessExplorervalIDation它们是否可以加载到其中)。 所以看起来我的系统configuration有问题,或者这个例子错了,或者根本无法从其他进程捕获事件。 任何人都可以启发我吗?

编辑2:好的,这是我的testing项目的来源。

包含挂钩过程的DLL:

library HookHelper; uses windows; {$R *.res} type THookCallback = procedure(ACode,AWParam,ALParam: Integer); stdcall; var WndHookCallback: THookCallback; Hook: HHook; function HookProc(ACode,ALParam: Integer): Integer; stdcall; begin Result := CallNextHookEx(Hook,ACode,ALParam); if ACode < 0 then Exit; try if Assigned(WndHookCallback) // and (ACode in [HSHELL_WINDOWCREATED,HSHELL_WINDOWDESTROYED]) then and (ACode in [HCBT_CREATEWND,HCBT_DESTROYWND]) then WndHookCallback(ACode,ALParam); except // plop! end; end; procedure InitHook(ACallback: THookCallback); register; begin // Hook := SetwindowsHookEx(WH_SHELL,@HookProc,HInstance,0); Hook := SetwindowsHookEx(WH_CBT,0); if Hook = 0 then begin // ShowMessage(SysErrorMessage(GetLastError)); end else begin WndHookCallback := ACallback; end; end; procedure UninitHook; register; begin if Hook <> 0 then UnhookwindowsHookEx(Hook); WndHookCallback := nil; end; exports InitHook,UninitHook; begin end.

而使用钩子的应用程序的主要forms:

unit MainFo; interface uses windows,SysUtils,Forms,Dialogs,Classes,Controls,buttons,StdCtrls; type THookTest_Fo = class(TForm) Hook_Btn: TSpeedbutton; Output_Lbx: TListBox; Test_Btn: Tbutton; procedure Hook_BtnClick(Sender: TObject); procedure Test_BtnClick(Sender: TObject); public destructor Destroy; overrIDe; end; var HookTest_Fo: THookTest_Fo; implementation {$R *.dfm} type THookCallback = procedure(ACode,ALParam: Integer); stdcall; procedure InitHook(const ACallback: THookCallback); register; external 'HookHelper.dll'; procedure UninitHook; register; external 'HookHelper.dll'; procedure HookCallback(ACode,ALParam: Integer); stdcall; begin if Assigned(HookTest_Fo) then case ACode of // HSHELL_WINDOWCREATED: HCBT_CREATEWND: HookTest_Fo.Output_Lbx.Items.Add('created handle #' + IntToStr(AWParam)); // HSHELL_WINDOWDESTROYED: HCBT_DESTROYWND: HookTest_Fo.Output_Lbx.Items.Add('destroyed handle #' + IntToStr(AWParam)); else HookTest_Fo.Output_Lbx.Items.Add(Format('code: %d,WParam: $%x,LParam: $%x',[ACode,ALParam])); end; end; procedure THookTest_Fo.Test_BtnClick(Sender: TObject); begin ShowMessage('Boo!'); end; destructor THookTest_Fo.Destroy; begin UninitHook; // just to make sure inherited; end; procedure THookTest_Fo.Hook_BtnClick(Sender: TObject); begin if Hook_Btn.Down then InitHook(HookCallback) else UninitHook; end; end.

windows将总是允许钩子和/或日志logging?

如何捕获任何正在运行的控制台进程的特定键盘序列?

如何在没有任何DLL注入的情况下返回一个窗口的句柄?

C ++跳转钩子

如何挂钩我自己的进程的所有 *** 作系统调用?

问题是你的钩子DLL实际上被加载到几个不同的地址空间。 任何时候,windows在一些必须由你的钩子处理的外部进程中检测到一个事件的时候,它会把钩子DLL加载到这个进程中(如果它还没有被加载的话)。

但是,每个进程都有自己的地址空间。 这意味着您在InitHook()中传递的回调函数指针只在您的EXE环境中有意义(这就是为什么它适用于您的应用程序中的事件)。 在其他任何指针是垃圾的过程中; 它可能指向一个无效的内存位置,或者(更糟糕的)进入一些随机代码段。 结果可能是访问冲突或无记忆内容损坏。

通常,解决方案是使用某种进程间通信 (IPC)来正确地通知您的EXE。 对于您的情况最无痛的方式是发布消息,并将所需的信息(事件和HWND)塞入到其WParaM / LParaM中。 您可以使用WM_APP + n或使用RegisterWindowMessage()创建一个。 确保邮件已发布,而不是发送,以避免任何死锁。

这可能是你的问题的第三大问题,但是正如你所看到的,钩子很难得到正确的结果 – 如果你可以避免使用这种方法,那就去做吧。 你会遇到各种各样的问题,特别是在Vista上,你将不得不面对UIPI。

只是为了澄清“efotinis”中提到的有关将消息发布回您的进程的内容 – 您发布到主进程的wParam和lParam不能是指针,它们只能是“数字”。

例如,让我们说你挂钩了WM_WINDOWPOSCHANGING消息,windows向你传递一个指向lparam中的WINDOWPOS的指针。 你不能把这个lparam放回你的主进程,因为lparam所指向的内存只在收到该消息的进程中有效。

当他说“将所需的信息(事件和HWND)塞入其WParaM / LParaM”时,这就是“efotinis”的意思。 如果你想传递更复杂的消息,你需要使用一些其他的IPC(如命名管道,TCP或内存映射文件)。

大声笑,它看起来像错误是在测试代码。

如果你创建两个单独的按钮,一个用于Init,一个用于UnInit(我更喜欢Exit)。

procedure THooktest_FO.UnInitClick(Sender: TObject); begin UninitHook; end; procedure THooktest_FO.InitClick(Sender: TObject); begin InitHook(HookCallback) end;

启动应用程序。 点击初始化,然后点击测试按钮,显示如下输出:

created handle #1902442 destroyed handle #1902442 created handle #1967978 created handle #7276488

然后显示消息框。

如果你点击确定你会得到:

destroyed handle #1967978

HTH

我找到了SetwindowsHookEx的Delphi基础文档。 但文字有点模糊。

function SetwindowsHookEx(IDHook: Integer; lpfn: TFNHookProc; hmod: HInst; DWThreadID: DWORD): HHOOK;

hmod:包含由lpfn参数指向的钩子函数的模块(DLL)的句柄。 如果DWThreadID标识由当前进程创建的线程,则该参数必须设置为零。dlpfn指向位于与当前进程关联的代码中的钩子函数。

DWThreadID:安装的钩子函数将被关联到的线程的标识符。 如果此参数设置为零,则挂钩将是与所有现有线程关联的全系统挂钩。

顺便说一句,对于hmod参数,你应该使用模块句柄。 (HINSTANCE指向应用程序句柄)。

hand := GetmoduleeHandle('hookhelper.dll'); Hook := SetwindowsHookEx(WH_SHELL,hand,0);

但是,虽然手与HINSTANCE不同,但仍显示相同的结果。

总结

以上是内存溢出为你收集整理的我需要做些什么来使我的WH_SHELL或WH_CBT挂钩程序从其他进程接收事件?全部内容,希望文章能够帮你解决我需要做些什么来使我的WH_SHELL或WH_CBT挂钩程序从其他进程接收事件?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/1272697.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存