信息发布软件,b2b软件,广告发布软件

 找回密码
 立即注册
搜索

VB.NET中的跨进程消息钩子和实例教程

查看数: 2888 | 评论数: 2 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2016-11-22 15:03

正文摘要:

 我们都知道在VB6里面可以用API函数来进行子类化,以处理自身的窗体过程;如果跨进程,这就麻烦了,由于我们的函数在我们的进程中(废话),而目标进程的窗口的消息处理函数在目标进程(还是废话),所以只能想办法 ...

回复

信息发布软件 发表于 2016-11-22 15:06:41

跨进程消息以及数据发送

    消息机制是WINDOWS的一个特点。在WINDOWS开发中基本上都会用到消息发送以及接收,突别是对于UI界面开发这一块。进程之间相互通信的方式有很多,其中包括跨进程消息。

消息发送 最常用的是使用SendMessage以及PostMessage 系统API函数,消息发到指定的窗口。不管是进程内或进程外我们都可以通过FindWindow 得到窗口句柄。

在进程内发送消息,我们可以发送一切所有定义的消息,如系统消息,或自定的消息,并通过LPARAM或WPARAM参数传递数据。因为我们所使用的数据内存是在同一进程内。那如果不是同一个进程内,还可以通过SendMessage以及PostMessage 系统API函数的LPARAM或WPARAM 参数传递数据吗? 答案是可以的,只是不能以进程内发送消息传递数据的方式。

不管是进程内还是进程外,消息都是会发送到系统消息队列里,然后由系统消息制机分发到指定窗口的。那么有人会问为何不能以进程内发送消息传递数据的方式呢? 因为,进程内与进程外数据的内存块并非在同一个区域,消息可以发送另外一个进程,但却不能访问进程外的数据,因而不能实现数据传递。

跨进程发送数据,Windows 系统提供一个强大的消息WM_COPYDATA。WM_COPYDATA可以实现进程间传递数据,但也就仅止于WM_COPYDATA消息内处理,不能发送控件定义的消息,以及自定义的消息。WM_COPYDATA 讨论的进程间数据传递的方法,那么除了WM_COPYDATA消息外,还有什么方法可以跨进程发送消息传递数据呢?

我们可以通过VirtualAllocEx 函数。它的作用是在指定进程的虚拟空间保留或提交内存区域。下现这用这方法实现跨进程发送系统消息,传递事件数据内容。以Tab控件为例


//查找窗口句柄
HWND hWnd = ::FindWindow(NULL,_T("MFCTabTest"));
if (hWnd)
  {
//获得窗口中 TAB 控件 句柄
   HWND childHwnd = ::FindWindowEx(hWnd, NULL, WC_TABCONTROL, NULL);   
   if (childHwnd)
   {
    //TAB 跳转到第一页面,可以正常发送消息以及系统类型数据如INT,BOOL 等。
   ::SendMessage(childHwnd, TCM_SETCURSEL, 1, 0L);
    //发送 TCN_SELCHANGING 事件通知
    {
     DWORD dwProcessId;

//获取进程ID
     GetWindowThreadProcessId( hWnd, &dwProcessId );

//打开进程
     HANDLEm_hProcess = OpenProcess( PROCESS_ALL_ACCESS, false, dwProcessId );
     if (!m_hProcess)  
return ;
//获取进程分配的虚拟空间内存块
    NMHDR * pNMHDR = NULL; //写入目标进程的NMHDR 结构
     pNMHDR = (NMHDR *)VirtualAllocEx( m_hProcess, NULL, sizeof(NMHDR), MEM_COMMIT,PAGE_READWRITE );
     if (!pNMHDR)  
return ;
//事件数据结构
     NMHDR mhdr;
     mhdr.hwndFrom = childHwnd;
     mhdr.code = TCN_SELCHANGING;
     mhdr.idFrom = 1000;
// 将本地进程中的结构写入到目标进程
     int nRet = WriteProcessMemory( m_hProcess, pNMHDR, &mhdr, sizeof(NMHDR), NULL );
//发送消息以及并传输结构数据
     ::SendMessage(hWnd,WM_NOTIFY,0,(LPARAM)pNMHDR);
//释入虚拟空间内存块
     VirtualFreeEx(m_hProcess,pNMHDR, sizeof(NMHDR),MEM_RELEASE);
    }
  }
  }


除了WM_COPYDATA外,利用虚拟空间也可以方便实现进程间数据通信。并且消息类型更完整,不管是系统消息还是自己定义的消息可以跨进程发送消息传递数据。


信息发布软件 发表于 2016-11-22 15:05:30

我们都知道在VB6里面可以用API函数来进行子类化,以处理自身的窗体过程;如果跨进程,这就麻烦了,由于我们的函数在我们的进程中(废话),而目标进程的窗口的消息处理函数在目标进程(还是废话),所以只能想办法把我们的代码放到对方进程中去执行——并且要告知我们的进程得到了什么消息。恐怕写汇编就有点吓人了,于是大家都写DLL,其原理就是把回调函数放到一个DLL里面注入到对方进程,DLL去修改目标窗口的默认处理函数——把消息发送给我们。

   当然也有“另类”一点的面有一个DLL包,其中含有一个dssubcls.dll,用它,可以轻松的完成我们的工作:就像调用一个API一样简单,而且在我们的程序中使用回调函数!呵呵,省去了自己写DLL的麻烦之后,这些好处足以吸引各位观众了吧?

   好了,VB6的代码大家可以在下载的压缩包中找到,作者提供了一个以记事本为基础的实例(在dssubcls目录下),非常详细无需详细叙述了。关键是在VB.NET里面如何使用它——如何声明API,如何进行回调,看用来子类化的API的VB6声明先:

  Declare Function SubClass& Lib "dssubcls" (ByVal HwndSubclass&, _

   Optional ByVal Address& = 0, _

   Optional ByVal OldStyle& = 0, _

   Optional ByVal NewStyle& = 0, _

   Optional ByVal Ext& = 0, _

   Optional ByVal SubClass& = 0)

  转化成VB.NET的声明类似下面的样子(习惯使然,我把&展开成了As Integer):

  Declare Function SubClass Lib "dssubcls" (ByVal HwndSubclass As Integer, Optional ByVal Address As Integer = 0, Optional ByVal OldStyle As Integer = 0, Optional ByVal NewStyle As Integer = 0, Optional ByVal Ext As Integer = 0, Optional ByVal SubClass As Integer = 0) As Integer

  这不是很好嘛?问题来了,这样的声明在VB6里面可以使用Addressof function来传入第二个参数(参见你下载的源码),但是在VB.NET里面直接Addressof就不成了——我们需要委托一个回调:

  Private Delegate Function HookCallBack(ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

  这个委托,对应的是以下函数:

   Private Function mCallback(ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

   ‘在这里处理得到的消息

   End Function

  使用时,需要注意先实例化这个委托:

   Private fix_COCD = New HookCallBack(AddressOf mCallback)

  此时,fix_COCD就是我们的mCallback函数引用了,用更直观的观点来看,fix_COCD就是一个指向mCallback的指针,相当于VB6里面的Addressof function得到的结果,看似问题解决了,于是我们写了以下代码来搞对方的进程窗体消息:

  SubClass(Handle, fix_COCD, 0, 0, 0, 1)   '修改处理函数

  问题真是接踵而至!IDE提示变量类型不符!!事实确实如此,我们把一个HookCallBack类型当做Integer来传递,无法通过检查,那么强行转换吧?当然,你可以去试试。这时,我所做的是,修改这个API声明:

  Private Declare Function SubClass Lib "dssubcls" (ByVal HwndSubclass As Integer, Optional ByVal Address As HookCallBack = Nothing, Optional ByVal OldStyle As Integer = 0, Optional ByVal NewStyle As Integer = 0, Optional ByVal Ext As Integer = 0, Optional ByVal SubClass As Integer = 0) As Integet

  使之符合我们的调用?有点倒行逆施?并非如此,当你习惯了修改API声明之后,会发现有些事变得如此简单,有些事需要你重新认识——对于WIN32 API也是如此。

  至此,大功告成:

  较为完整的代码如下:


    Private Declare Function SubClass Lib "dssubcls" (ByVal HwndSubclass As Integer, Optional ByVal Address As HookCallBack = Nothing, Optional ByVal OldStyle As Integer = 0, Optional ByVal NewStyle As Integer = 0, Optional ByVal Ext As Integer = 0, Optional ByVal SubClass As Integer = 0) As Integer    Private Declare Function UseSendmessage Lib "dssubcls" (ByVal use As Integer) As Integer    '实例化的委托    Private fix_COCD = New HookCallBack(AddressOf mCallback)    '委托    Private Delegate Function HookCallBack(ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer    Public Sub Hook(ByVal Handle As Integer)        proc = SubClass(Handle, fix_COCD, 0, 0, 0, 1)   '修改处理函数        UseSendMessage(1)    End Sub    Private Function mCallback(ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer    End Function

QQ|( 京ICP备09078825号 )

本网站信息发布软件,是可以发布论坛,发送信息到各大博客,各大b2b软件自动发布,好不夸张的说:只要手工能发在电脑打开IE能发的网站,用这个宣传软件就可以仿制动作,进行推送发到您想发送的B2B网站或是信息发布平台上,不管是后台,还是前台,都可以进行最方便的广告发布,这个广告发布软件,可以按月购买,还可以试用软件,对网站的验证码也可以完全自动对信息发布,让客户自动找上门,使企业轻松实现b2b发布,这个信息发布软件,均是本站原创正版开发,拥有正版的血统,想要新功能,欢迎提意见给我,一好的分类信息群发软件在手,舍我其谁。QQ896757558

GMT+8, 2024-11-27 13:08 , Processed in 0.127341 second(s), 42 queries .

宣传软件--信息发布软件--b2b软件广告发布软件

快速回复 返回顶部 返回列表