我试图使用一个简单的VBA宏自动化一个基于网络的应用程序。首先,它是为一家公司,我的工作,因此应用程序是在安全的citrix环境。我启动它使用“应用程序启动器”程序。
我尝试我的手使用windows API。一个重要的限制,citrix环境,是我不能安装spy++在它上面。因为公司不允许它。因此,我使用另一个VBA代码,我发现在互联网上实际列出所有的窗口,对象,处理我的机器。这个代码是由马克罗林森写的。
现在,我尝试使用这些有限的信息来自动化GUI访问。
步骤1:使用App Launcher程序启动应用程序。x1c 0d1x
第2步:启动swift登录页面后,我单击HSM框选项。
步骤3:点击HSM框后,我们需要在下面的屏幕上填写用户名,密码和会话PIN。
在这里,我自动执行了步骤2,在该步骤中启动swift登录(手动单击),然后单击HSM盒选项(自动使用VBA)。但在第3步之后,我无法继续前进,因为我无法找到正确的句柄。如前所述,我不能使用spy ++,因为它不允许安装任何第三方软件。因此,我使用另一个VBA代码只是为了列出给定页面上的所有句柄。那么在这种情况下,我如何确定要单击哪个元素呢?
下面是我正在使用的代码。
我的VBA代码自动化步骤2。这是工作正常。
Private Declare PtrSafe Function apiGetClassName Lib "User32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function apiGetDesktopWindow Lib "User32" Alias "GetDesktopWindow" () As Long
Private Declare PtrSafe Function apiGetWindow Lib "User32" Alias "GetWindow" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Private Declare PtrSafe Function apiGetWindowLong Lib "User32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function apiGetWindowText Lib "User32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal aint As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function FindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare PtrSafe Function SendMessageByString Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Declare Function GetWindowText Lib "User32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Const mcGWCHILD = 5
Private Const mcGWHWNDNEXT = 2
Private Const mcGWLSTYLE = (-16)
Private Const mcWSVISIBLE = &H10000000
Private Const mconMAXLEN = 255
Private Const BM_CLICK As Integer = &HF5
Private Const WM_ACTIVATE As Integer = &H6
Private Const WA_ACTIVE As Integer = &H1
Sub ClickPrintButtonWindowsAPI()
Dim hw As Long, mxtextbox As Long, tokenbutton As Long
Dim pwd As String
hw = FindWindow(vbNullString, "xxxxx xxx SWIFT Login")
MsgBox hw
tokenbutton = FindWindowEx(hw, 0&, "Button", "HSM Box")
MsgBox tokenbutton
Call SendMessage(tokenbutton, WM_ACTIVATE, 0, 0)
Call SendMessage(tokenbutton, BM_CLICK, 0, 0)
subwindow = FindWindowEx(hw, 0&, "ComboBox", vbNullString)
MsgBox subwindow
pwdTxtbox = FindWindowEx(subwindow, 0&, "Edit", vbNullString)
MsgBox pwdTxtbox
Call SendMessage(pwdTxtbox, WM_ACTIVATE, 0, 0)
Call SendMessageByString(pwdTxtbox, WM_SETTEXT, 0, "xxxxxxxx")
End Sub
VBA代码,我正在使用从马克罗林森列出所有的窗口,句柄,对象等。
Option Explicit
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private x As Integer
'Used a user defined type here rather than Enum so that it works on 97
Private Type winEnum
winHandle As Integer
winClass As Integer
winTitle As Integer
winHandleClass As Integer
winHandleTitle As Integer
winHandleClassTitle As Integer
End Type
Dim winOutputType As winEnum
Public Sub GetWindows()
x = 0
winOutputType.winHandle = 0
winOutputType.winClass = 1
winOutputType.winTitle = 2
winOutputType.winHandleClass = 3
winOutputType.winHandleTitle = 4
winOutputType.winHandleClassTitle = 5
GetWinInfo 0&, 0, winOutputType.winHandleClassTitle
End Sub
Private Sub GetWinInfo(hParent As Long, intOffset As Integer, OutputType As Integer)
'Sub to recursively obtain window handles, classes and text
'given a parent window to search
'Written by Mark Rowlinson
'www.markrowlinson.co.uk - The Programming Emporium
Dim hWnd As Long, lngRet As Long, y As Integer
Dim strText As String
hWnd = FindWindowEx(hParent, 0&, vbNullString, vbNullString)
While hWnd <> 0
Select Case OutputType
Case winOutputType.winClass
strText = String$(100, Chr$(0))
lngRet = GetClassName(hWnd, strText, 100)
Range("a1").Offset(x, intOffset) = Left$(strText, lngRet)
Case winOutputType.winHandle
Range("a1").Offset(x, intOffset) = hWnd
Case winOutputType.winTitle
strText = String$(100, Chr$(0))
lngRet = GetWindowText(hWnd, strText, 100)
If lngRet > 0 Then
Range("a1").Offset(x, intOffset) = Left$(strText, lngRet)
Else
Range("a1").Offset(x, intOffset) = "N/A"
End If
Case winOutputType.winHandleClass
Range("a1").Offset(x, intOffset) = hWnd
strText = String$(100, Chr$(0))
lngRet = GetClassName(hWnd, strText, 100)
Range("a1").Offset(x, intOffset + 1) = Left$(strText, lngRet)
Case winOutputType.winHandleTitle
Range("a1").Offset(x, intOffset) = hWnd
strText = String$(100, Chr$(0))
lngRet = GetWindowText(hWnd, strText, 100)
If lngRet > 0 Then
Range("a1").Offset(x, intOffset + 1) = Left$(strText, lngRet)
Else
Range("a1").Offset(x, intOffset + 1) = "N/A"
End If
Case winOutputType.winHandleClassTitle
Range("a1").Offset(x, intOffset) = hWnd
strText = String$(100, Chr$(0))
lngRet = GetClassName(hWnd, strText, 100)
Range("a1").Offset(x, intOffset + 1) = Left$(strText, lngRet)
strText = String$(100, Chr$(0))
lngRet = GetWindowText(hWnd, strText, 100)
If lngRet > 0 Then
Range("a1").Offset(x, intOffset + 2) = Left$(strText, lngRet)
Else
Range("a1").Offset(x, intOffset + 2) = "N/A"
End If
End Select
'check for children
y = x
Select Case OutputType
Case Is > 4
GetWinInfo hWnd, intOffset + 3, OutputType
Case Is > 2
GetWinInfo hWnd, intOffset + 2, OutputType
Case Else
GetWinInfo hWnd, intOffset + 1, OutputType
End Select
'increment by 1 row if no children found
If y = x Then
x = x + 1
End If
'now get next window
hWnd = FindWindowEx(hParent, hWnd, vbNullString, vbNullString)
Wend
End Sub
下面是运行上述代码后在excel中的输出。
如果你能在这里看到,下面是用户名和密码的句柄名称和值。我怎样才能选择“密码”编辑框?它的值是N/A。
- 1640324静态用户名
- 722818编辑不适用
- 722816静态密码
- 722814编辑不适用
我需要出去的路。
此外,第一步解析通过应用程序启动程序的树结构也是不可能的,因为间谍++相同的限制。我该怎么办?
1条答案
按热度按时间x4shl7ld1#
谢谢Gserg的提示。我自己也解决了这个问题,通过递归引用。例如,类似下面的内容
这样我就可以解析同一级别的所有编辑句柄,直到找到正确的句柄。