一个使用Hook的例子,高手给看看问题在哪儿?(200分)

  • 主题发起人 主题发起人 windz
  • 开始时间 开始时间
W

windz

Unregistered / Unconfirmed
GUEST, unregistred user!
这个iCode是个什么东西,什么时候它才可以等于HCBT_CREATEWND?<br><br>Function ShellDll_MainHook(iCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; export;<br>Const<br>&nbsp; FExePath = '/Software/MCR/MSNChatRecorder';<br>&nbsp; FExeKey = 'ExePath';<br>&nbsp; FNewChat = 'NewChat';<br><br>&nbsp; FMSNPath = '/Software/Microsoft/MSNMessenger';<br>&nbsp; FMSNUserKey = 'USER.NET Messenger Service';<br><br><br>Var<br>&nbsp; szClass: Array[0..MAX_PATH] Of Char;<br>&nbsp; hwndToNewWindow: HWND;<br>&nbsp; ChildWindow: Thandle; //对话记录窗体<br>&nbsp; NameWindow: Thandle; //对话者窗体<br>&nbsp; TxtFile: TextFile;<br><br>&nbsp; Name_lptstr: pchar; //拷贝的内容<br>&nbsp; Name_CPHandle: THandle; //临时内存句柄<br><br>&nbsp; Text_lptstr: pchar; //拷贝的内容<br>&nbsp; Text_CPHandle: THandle; //临时内存句柄<br><br>&nbsp; TxtFilePath: wideString; //Txt文件路径<br>&nbsp; ChatTxt1: String; //对话内容<br>&nbsp; EMailName: String;<br>&nbsp; Reg: TRegistry;<br><br>&nbsp; i: integer;<br>Begin<br>&nbsp; Try<br>&nbsp; &nbsp; Reg := TRegistry.Create;<br><br>&nbsp; &nbsp; //CreateTxtFile<br>&nbsp; &nbsp; Reg.RootKey := HKEY_LOCAL_MACHINE;<br>&nbsp; &nbsp; Reg.OpenKey(FExePath, false);<br>&nbsp; &nbsp; TxtFilePath := Reg.ReadString(FExeKey);<br>&nbsp; &nbsp; Reg.CloseKey;<br><br>&nbsp; &nbsp; Reg.RootKey := HKEY_CURRENT_USER;<br>&nbsp; &nbsp; If Reg.OpenKey(FMSNPath, False) Then<br>&nbsp; &nbsp; &nbsp; TxtFilePath := TxtFilePath + 'Test';<br>&nbsp; &nbsp; Reg.CloseKey;<br>&nbsp; Finally<br>&nbsp; &nbsp; Reg.Free;<br>&nbsp; End;<br>&nbsp; If iCode &lt; 0 Then<br>&nbsp; &nbsp; Result := CallNextHookEx(g_hShellHook, iCode, wParam, lParam);<br><br>&nbsp; If iCode = HCBT_CREATEWND Then<br>&nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; hwndToNewWindow := HWND(wParam);<br>&nbsp; &nbsp; &nbsp; GetClassName(hwndToNewWindow, szClass, MAX_PATH);<br>&nbsp; &nbsp; &nbsp; If StrComp(szClass, pchar('IMWindowClass')) = 0 Then <br>&nbsp; &nbsp; &nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NameWindow := FindWindowEx(hwndToNewWindow, NameWindow, PChar('Edit'), Nil);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(NameWindow, EM_SETSEL, 0, -1); <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(NameWindow, WM_COPY, 0, 0);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(NameWindow, EM_SETSEL, -1, 0); <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OpenClipboard(0);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name_CPHandle := GetClipboardData(CF_TEXT);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name_lptstr := pchar(GlobalLock(Name_CPHandle));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalUnlock(Name_CPHandle);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EMailName := Name_lptstr;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TxtFilePath := TxtFilePath + '/' + GetEMailName(EMailName);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EmptyClipboard;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CloseClipboard;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; For i := 0 To 1 Do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ChildWindow := FindWindowEx(hwndToNewWindow, ChildWindow, PChar('RichEdit20W'), Nil);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(ChildWindow, EM_SETSEL, 0, -1); <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(ChildWindow, WM_COPY, 0, 0);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(ChildWindow, EM_SETSEL, -1, 0); <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OpenClipboard(0);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text_CPHandle := GetClipboardData(CF_TEXT);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text_lptstr := pchar(GlobalLock(Text_CPHandle));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalUnlock(Text_CPHandle);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ChatTxt1 := Text_lptstr;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EmptyClipboard;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CloseClipboard;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If StrLen(pchar(ChatTxt1)) &gt; 50 Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Try<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AssignFile(TxtFile, TxtFilePath + '.txt');<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If Not FileExists(TxtFilePath + '.txt') Then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Rewrite(TxtFile)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Append(TxtFile);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ChatTxt1 := Copy(ChatTxt1, 51, length(ChatTxt1) - 48);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Writeln(TxtFile, '对话日期:' + DateToStr(Now) + ' 对话时间:' + TimeToStr(Time));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Writeln(TxtFile, ChatTxt1);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Writeln(TxtFile, '-*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*-');<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Finally<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CloseFile(TxtFile);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; End;<br>&nbsp; &nbsp; &nbsp; &nbsp; End;<br><br>&nbsp; &nbsp; End;<br>&nbsp; Result := CallNextHookEx(0, iCode, wParam, lParam);<br>End;<br>
 
iCode用于决定如何处理信息,其具体含义取决于你的Hook的类型,<br>查SetWindowsHookEx的帮助可以找到所有Hook类型的定义。
 
谢谢thx1180。<br>这段代码是网上找的,用来捕获msn的消息并存储的,但里面似乎有问题,<br>该触发的触发不了,不该触发的却触发了。<br>我查了SetWindowsHookEx,使用的是WH_CBT。<br>Installs a hook procedure that receives notifications useful to <br>a computer-based training(CBT) application.<br><br>关键是If iCode = HCBT_CREATEWND Then这一行总也进不去。<br>他这么写对吗?<br>我没写过Hook,麻烦给指导一下。
 
老大,你真的要做MSN的助手那样的软件吗?我支持你!!<br>但我不会,帮不了你,帮你up吧
 
我不是要做这样的软件,只是已经有这样的软件做出来了,而且是Delphi写的。<br>所以我就感兴趣。<br>谢谢小笨笨up。
 
Try<br>&nbsp; &nbsp; Reg := TRegistry.Create;<br><br>&nbsp; &nbsp; //CreateTxtFile<br>&nbsp; &nbsp; Reg.RootKey := HKEY_LOCAL_MACHINE;<br>&nbsp; &nbsp; Reg.OpenKey(FExePath, false);<br>&nbsp; &nbsp; TxtFilePath := Reg.ReadString(FExeKey);<br>&nbsp; &nbsp; Reg.CloseKey;<br><br>&nbsp; &nbsp; Reg.RootKey := HKEY_CURRENT_USER;<br>&nbsp; &nbsp; If Reg.OpenKey(FMSNPath, False) Then<br>&nbsp; &nbsp; &nbsp; TxtFilePath := TxtFilePath + 'Test';<br>&nbsp; &nbsp; Reg.CloseKey;<br>&nbsp; Finally<br>&nbsp; &nbsp; Reg.Free;<br>&nbsp; End;<br><br><br>这一段放在前面干嘛? 应该放在If iCode = HCBT_CREATEWND Then后面<br><br><br>还有你的SetWindowsHookEx是怎么写的?
 
HCBT_CREATEWND 是在一个窗口新建前发生的
 
那段代码没什么用,我已经删了。<br><br>SetWindowsHookEx如下:<br>Function EnableHook: BOOL; export;<br>Begin<br>&nbsp; g_hShellHook := SetWindowsHookEx(WH_CBT, ShellDll_MainHook, HInstance, 0);<br>End;<br><br>我很怀疑,使用HCBT_CREATEWND对吗?<br>可是我又找到了一个C版本的,也是这么写的。<br>
 
If iCode &lt; 0 Then<br>begin<br>&nbsp; &nbsp; Result := CallNextHookEx(g_hShellHook, iCode, wParam, lParam);<br>&nbsp; &nbsp; exit;//增加这一句<br>end;<br><br><br>最后一句: Result := CallNextHookEx(0, iCode, wParam, lParam);<br>改为:Result := CallNextHookEx(g_hShellHook, iCode, wParam, lParam);<br><br><br>
 
多谢wbtvc,但是还是不行。<br><br>和以前一样,只能勾到主窗口的HCBT_ACTIVATE,对其他窗口没有响应。<br><br>我跟踪了ShellDll_MainHook,只有从其他窗口切换到主窗口时,才执行此函数。<br>而且执行两次。第一次iCode为5,第二次iCode为9。<br>HCBT_ACTIVATE = 5<br>HCBT_SETFOCUS = 9<br>更改Result := CallNextHookEx(g_hShellHook, iCode, wParam, lParam)后,<br>此函数要执行两次以上。<br>
 
从以前的帖子里查到这样一句话:<br><br>首先要说明的是WH_CBT是不能拦截WM_Close的,用WH_CALLWNDPROC 吧,可以挂到,但是有个问题<br><br>不知道WH_CBT对MSN的发送和接收数据能不能截到?
 
对其他窗口没有响应?<br>如果以上函数是放在dll里应该可以呀<br><br>WH_CBT只能截取窗口创建,激活,最大小化等之类的消息<br>HCBT_CREATEWND是一个窗口创建前发生的(以前窗口尚未存在的),<br>HCBT_ACTIVATE是窗口激活时发生的(以前窗口就存在的,)<br>两者有本质的不同<br><br>WH_CALLWNDPROC 截取使用sendmessage发送的消息<br><br><br><br>或者贴出你的全部代码。<br>
 
我用WH_CALLWNDPROC再试试。<br><br>全部代码太多了,您能给个邮箱吗?<br>截到的数据还有一个中文的问题,如果问题都解决了,还有300分奉送。<br>我的邮箱:wind_cn@163.com<br>谢谢了。<br>
 
sxmwbt@163.com<br><br>
 
已经发了。
 
代码已收到(好像有点乱,改过了吧,呵呵),不好意思,刚睡醒。<br><br>问题出在这里:<br>&nbsp;If iCode = HCBT_CREATEWND Then<br>&nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; hwndToNewWindow := HWND(wParam);<br>&nbsp; &nbsp; &nbsp; GetClassName(hwndToNewWindow, szClass, MAX_PATH);<br>&nbsp; &nbsp; &nbsp; If StrComp(szClass, pchar('IMWindowClass')) = 0 Then <br>&nbsp; &nbsp; &nbsp; &nbsp; Begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NameWindow := FindWindowEx(hwndToNewWindow, NameWindow,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PChar('Edit'), Nil);<br><br>问题在于HCBT_CREATEWND是在窗口刚创建时发生的,他的其他子窗口子控件这时<br>尚未创建,所以这时你找到的NameWindow为0,也就等于没找到正确的Edit的句柄。<br>
 
你的Hook是没错的,可以Hook到HCBT_CREATEWND这个消息的。<br>A window is about to be created. <br>The system calls the hook procedure <br>before sending the WM_CREATE or <br>WM_NCCREATE message to the window. <br>If the hook procedure returns a nonzero value,<br>&nbsp;the system destroys the window; <br>the CreateWindow function returns NULL, <br>but the WM_DESTROY message is not sent <br>to the window. If the hook procedure <br>returns zero, the window is created normally.<br>At the time of the HCBT_CREATEWND <br>notification, the window has been created, <br>but its final size and position may not<br>&nbsp;have been determined and its parent <br>window may not have been established. <br>It is possible to send messages to <br>the newly created window, although <br>it has not yet received WM_NCCREATE <br>or WM_CREATE messages. It is also <br>possible to change the position in <br>the Z order of the newly created <br>window by modifying the hwndInsertAfter <br>member of the CBT_CREATEWND structure.
 
所以你改为WH_CALLWNDPROC试试,应该可以的
 
如果有中文的问题,是因为你是在win2000或xp下运行吧?<br>那就应该将char、pchar改为widechar、pwidechar
 
改成WH_CALLWNDPROC果然就好了,非常感谢!<br>中文也没有问题。<br>(我写的另外一个钩子有中文问题。不过我确实在W2K下运行的,果然厉害!)<br><br>还有两个问题请教一下:<br>1、在我写钩子记录窗口标题的时候,我使用了HCBT_DESTROYWND,但它显然无法对付<br>像IE这样标题不断变化的情况。有没有更好的判断标志?<br>2、如果我已经得到了一个窗口的句柄,怎样判断该窗口是否为隐含窗口?<br><br>新开了一个帖子送分,请留意查收。<br>谢谢。
 
后退
顶部