C/S架构中被测试对象,有很多是在窗口中自绘的或自定义控件,用SYP++这类工具只能定位到窗体,无法再定位到窗体里的控件了。 一开始并不知道如何处理。问了很多人,最后用windows API 中的SendMessage函数给被测试对象句柄发消息达到和被测试对象的通讯,就可以做一些操作。下面分享一下具体实现
首先说一下,由于QTP中调试实在是太慢了。所以下了个VB6来调试。又由于在百度上了很久没有VBS使用sendmessage的写法。只好又查VB中sendmessage的写法。过程真是费事。
然后测试了VB用Sendmessage发送消息实现了关闭窗口,记事本输入文字的例子。先保证使用方法是对的。再去做向被测试对象发消息,由于被测试对象发的消息是自定义的,一直没被接收到。
就又百度VB接收自定义消息,做了个接收的程序。自己在VB中调试接收到的消息对不对。发现自定义消息是按16进制来定义的。就是接收端自定义的消息WM_USER+1。WM_USER=&H400这个是16进制的表达式。&H400+1转成十进制是1025。我用sendmessage的第二个参数msg就要用WM_USER+1,或者用1025。
1.VB中发送消息例子
在VB6的模块中写入下面代码,这个定义如果放在form1上面,就不能定义为public .要定义为private
- Public Const WM_USER = &H400
- Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
- Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
复制代码在Form1写入以下代码 - Private Sub Command1_Click()
- Dim hwnd As Long
- Shell "E:……\接收消息的.exe", vbNormalFocus '打开接收消息的程序
- hwnd = FindWindow(vbNullString, "Form1") '这个参数的第一个是类名称,第二个市窗体的标题 得到接收消息程序的句柄
- SendMessage hwnd, 1025, 0, 0 '向hwnd这个句柄发消息
- End Sub
复制代码
2.接收消息的代码 - '模块中代码
- Public prevWndProc As Long
- Public Const GWL_WNDPROC = (-4)
- Public Const WM_USER = &H400
- Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
- Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
- Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
- Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
- Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
- If Msg = WM_USER + 1 Then '在这里处理你的消息(嘿!!!!别看花眼了,向这看!!!!!!!) --尊重原作 ,这个是原作的注释挺有意思的。
- MsgBox Msg
- Else
-
- WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
- 'MsgBox Msg & "消息不对" '这个打开发现很有意思的一个现象,原来不断地会有不同的消息发过来。估计是window有此消息是广播的方式
- End If
- End Function
复制代码- ’在Form1中的代码
- '这个是测试用的。
- Private Sub Command1_Click()
- SendMessage Me.hwnd, 1024, 0, 0
- End Sub
- Private Sub Form_Load()
- Me.AutoRedraw = True
- Print Me.hwnd '打印本窗口真实句柄,对照发消息findWindow获取的句柄是否正确
- prevWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
- SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WndProc
- End Sub
- '正常关闭窗口
- Private Sub Form_Unload(Cancel As Integer)
- SetWindowLong Me.hwnd, GWL_WNDPROC, prevWndProc
- End Sub
复制代码 SendMessage(句柄,消息,参数1,参数2) 是发消息函数,
FindWindow (类名,窗口标题名) 得到窗口句柄
CallWindowProc 是将消息信息传送给指定的窗口过程的函数
GetWindowLong 该函数获得指定窗口的有关信息,函数也获得在额外窗口内存中指定偏移位地址的32位度整型值。得到窗口新地址值GWL_WNDPROC = (-4)
SetWindowLong 该函数用来改变指定窗口的属性.函数也将指定的一个32位值设置在窗口的额外存储空间的指定偏移位置?设置窗口新地址为值GWL_WNDPROC = (-4)
详细查VB API。Window API
===========================华 丽 丽 的 分 划 线=========================================================================== QTP中不能直接用VB的写法,要转为VBS写法。想想挺麻烦的,为什么不一个语言一统天下。 VBS sendmessage使用方法 可以根据发送的消息让被测试程序做一些操作如重启,打开啊。也可以返回消息如控件属性。这些都需要和开发沟通。慢慢也就成了测试开发了。
还有个方法是用进程注入测试后门,通过socket和后门通信实现测试,还没研究,研究后再分享。其它没想到还有什么办法。请分享更好的方法。 如果用UIAoutomotion框架是不是会更简单一些?
|