17 Working with APIs
Concept: The MS API (Application Programming Interface)provides various functions to do operations like getting cursor coordinates,window handles, colors etc. But due to VBS limitations, only limited APIs canbe used in QTP.
Extern Object:
Syntax
Extern.Declare(RetType, MethodName, LibName, Alias [, ArgType(s)]) RetType: Data type of the value returned by the method. MethodName : Any valid procedure name. LibName : Name of the DLL or code resource (c:\mydll.dll)that contains the declared procedure. Alias : Name of the procedure in the DLL or code resource. Can be blank. ArgType: arguments that are passed to the procedure E.g. extern.Declare micLong,"GetForegroundWindow","user32.dll","GetForegroundWindow" |
17.1 How can we get the topmost window?
Note:the topmost window 是QTP.
extern.Declare micLong,"GetForegroundWindow","user32.dll","GetForegroundWindow"
'Get the handle of the top most window hwnd = extern.GetForegroundWindow() hwndPro = "hwnd:= " & hwnd 'Check if a browser with that window handle exists isBrowser = Window(hwndPro).Exist(2) ‘Or isBrowser = Browser(hwndPro).Exist(2) |
17.2 How can we get the value of Windows Environment variables (not QTP Environmentvariables)?
'Declare the API GetEnvironmentVariable Extern.Declare micLong,"GetEnvironmentVariable","kernel32.dll","GetEnvironmentVariableA", _ micString,micString+micByRef,micLong
'Get the environment variable "TEMP" value Extern.GetEnvironmentVariable "TEMP",s_EnvValue,255 'This will get the path for the temporary folder. print s_EnvValue ‘C:\Users \AppData\Local\Temp |
17.3 How can we check (select) an item from a List Box using a Windows API?
Extern.Declare micLong,"SendMessage","user32.dll","SendMessageA",micLong,micLong,micLong,micLong
'List Box message to set a selection Const LB_SETSEL = &H185
'Function to check the box at given index Function CheckListBox(hwnd, index) extern.SendMessage hwnd, LB_SETSEL, True, index end function
'Function to uncheck the box at given index Function UnCheckListBox(hwnd, index) extern.SendMessage hwnd, LB_SETSEL, False, index end function |
17.4 How can we get the background color of a text box?
'Declare all the needed APIs Extern.Declare micLong,"GetPixel","gdi32","GetPixel",micLong,micLong,micLong Extern.Declare micLong,"GetWindowDC","user32","GetWindowDC",micLong Extern.Declare micLong,"ReleaseDC","user32","ReleaseDC",micLong,micLong Extern.Declare micLong,"GetDC","user32","GetDC",micLong Extern.Declare micLong,"SetForegroundWindow","user32","SetForegroundWindow",micLong
Dim hDCSource Dim hWndSource Dim backColor 'Get the handle of the control
hWndSource =Browser("b").Page("p"). WinEdit("Edit_4").GetROProperty("hwnd") 'Bring the window to foreground. This is important as GetPixel works only on visible pixels extern.SetForegroundWindow hWndSource
'Get the devic context handle hDCSource = Clng(Extern.GetDC(hWndSource)) 'Get the background color of pixel 1,1 relative to the control. backColor = Clng(Extern.GetPixel(hDCSource, Clng(1),Clng(1)))
print backColor 'Release the device context handle Extern.ReleaseDC hWndSource, hDCSource |
17.5 How can we simulate a keyboard event using a Windows API?
'Declare all the needed APIs Extern.Declare micVoid,"keybd_event","user32","keybd_event",micbyte,micbyte,micLong,micLong Extern.Declare micLong,"MapVirtualKey","user32","MapVirtualKeyA",micLong, micLong
Const KEYEVENTF_EXTENDEDKEY = &H1 Const KEYEVENTF_KEYUP = &H2 Const KEYEVENTF_KEYDOWN = &H0
Sub KeyDown (keyAscii) keyCode = extern.MapVirtualKey(keyAscii, 0) extern.keybd_event keyAscii, keyCode, KEYEVENTF_KEYDOWN, 0 End Sub
Sub KeyUp (keyAscii) keyCode = extern.MapVirtualKey(keyAscii, 0) extern.keybd_event keyAscii, keyCode, KEYEVENTF_KEYUP, 0 End Sub
Sub KeyPress (keyAscii) KeyDown keyAscii KeyUp keyAscii End Sub
Call KeyPress (49) '1 key pressed Call KeyPress (13) 'enter key |
Using the above code to simulate CTRL+ALT+S
‘Control =17; alt = 18; S=83 Call KeyDown(17) Call KeyDown(18) Call KeyDown(83 ) Call KeyUp(83 ) Call KeyUp(18) Call KeyUp(17) |
17.6 How can we prevent a PC from being locked by its screen saver?
Extern.Declare imcVoid,"keybd_event","user32","keybd_event", micByte,micByte,micLong,micLong Extern.Declare imcVoid,"Sleep","kernel32","Sleep", micLong
Const KEYEVENTF_KEYUP = &H2 While Ture extern.keybd_event 0, 0, KEYEVENTF_KEYUP, 0 extern.Sleep 20000 Wend |
Note: The above code may produce error because bin folder ofQTP should be added to windows PATH environment variable. Here is the code:
'Function to add a folder to PATH Public Function AddToSystemPath(ByVal Path) Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
'Get the windows environment Set colItems = objWMIService.ExecQuery _ ("Select * From Win32_Environment Where Name = 'Path'")
For Each objItem in colItems 'Add to PATH only if the path does not already exists If InStr(objItem.VariableValue, Path)= 0 Then 'If path does not exist already then add it strPath = objItem.VariableValue & ";" & Path objItem.VariableValue = strPath objItem.Put_ End If Next End Function
AddToSystemPath "C:\Program Files\Mercury Interactive\QuickTest Professional\bin" |
17.7 How can we maximize a window or a browser?
Private Const SW_MAXIMIZE = 3 Extern.Declare micLong, "ShowWindow", "user32.dll", "ShowWindow", _ micHwnd, micLong
'In case we want to maximize a window then handle 'of that window needs to be used. hWndWindow = Browser("title:=about:blank").GetROProperty("hwnd") print hWndWindow 'Maximize the window Extern.ShowWindow hWndWindow, SW_MAXIMIZE |
17.8 How can we download a file form a URL to disk?
Extern.Declare micLong, "URLDownloadToFile", "urlmon", "URLDownloadToFileA", micLong, micString, micString, micLong, micLong
sSourceURL = "http://www.baidu.com/img/baidu_sylogo1.gif" sTargetFile = "C:\logon.gif"
extern.URLDownloadToFile 0, sSourceURL, sTargetFile, 0, 0 |
Using VB DLL in QTP:
Since VBS only support variant data type, not use structure.So API use COM object in VB.
'Steps to use API COM object in vb '1. registed DLL on PC: regsvr32 "C:\my.dll" '2. Access DLL in QTP Set winAPI = CreateObject("WindowsAPI.API") ‘<ProjectName>.<ClassName> winAPI.Method1(args) |
Running API Using Excel
Using Excel COM APIS to create a custom COM library: usingMacro.
‘Steps to create Macros in excel 1. Press ALT+F11 to VB Editor 2. Record/Script VB Macro 3. Call the Macro in QTP using VBS |
总而言之: 就是调人家excel写好了的宏,就不用自己写宏已经实现的功能。
Dynamicallygenerating an Excel Macro
This generates the needed macro at the run-time using VBEacutomation Classes.
‘Method 1: importMacro at run-time
‘Smaple Code: Set xlsVBComponents = xlsWorkbook.VBProject.VBComponents 'Import the code xlsVBComponents.Import "C:\MyCode.Bas" xlsApp.Run "MacroFunction", argments |
Note: it wills error (“Trust access to Visual Basicproject”), set Excel “ToolsàMacroàSecurity…àTrusted Publishers (Tab)à Check the check box (Trustaccess to VB project)”; or using following code set security status:
Set oShell = CreateObject("WScript.Shell") 'Enable Trust Access oShell.RegWrite "HKLM\SOFTWARE\Microsoft\Office\11.0\Excel\Security\AccessVBOM", 1, "REG_DWORD" 'Disable Trust Access oShell.RegDelete "HKLM\SOFTWARE\Microsoft\Office\11.0\Excel\Security\AccessVBOM" |
‘Method 2:
'Create the module file Const vbext_ct_StdModule = 1 Set oModule = xlWorkbook.VBProject.VBComponents.Add (vbext_ct_StdModule) oModule.Name = "MyCode" 'Add code using file oModule.CodeModule.AddFromFile "C:\MyCode.Bas" |
‘Method 3: Coding Macro as Sting.
'Get a refernce to ThisWorbook Set oModule = xlsWorkbook.VBProject.VBComponents.Item ("ThisWorkbook")
'Create the code in a string Dim newCode newCode = "Public Sub TestThis(ByVal pParam as string)" + vbNewLine newCode = newCode + "Msgbox pParam" + vbNewLine newCode = newCode + "End Sub" + vbNewLine
'Add the code from a string oModule.CodeModule.AddFromString newCode
'Access the function we just added xlsWorkbook.TestThis "Tarun Lalwani" |
Workingwith Modal dialog boxes:
QTP Recovery scenario does not help if no error occurs.
Here are possible API solutions:
FindWindow: get window handle for a specific window. |
FindWindowEx: get a child object of specified window, e.g. OK button in the dialog box |
PostMessage: Send a message to a specific window’s message queue. |
SetActiveWindow: Set the window active. |
Method1: cannot used if not sure when window will appear.
To close non QTP message box, find the handle of dialog withtitle, get its child button to close the dialog and send the message to clickthat button:
'API declarations Extern.Declare micLong,"FindWindow","user32.dll","FindWindowA", _ micString,micString Extern.Declare micLong,"FindWindowEx","user32.dll","FindWindowExA", _ micLong,micLong,micString,micString Extern.Declare micLong,"PostMessage","user32.dll","PostMessageA", _ micLong,micLong,micLong,micRef+micLong Extern.Declare micLong,"SetActiveWindow","user32.dll","SetActiveWindow", _ micLong
'Constant for the Click event message for a button Private Const BN_CLICK = 245
'Note the window and button name are case sensitive sWindowName = "Test Window" sWindowButton = "OK"
'Get the window handle from window caption/title hwndWindow = Extern.FindWindow (vbNullString,sWindowName)
'If we find a non-zero handle If hwndWindow Then 'find the handle to the button inside the window hwndButton = Extern.FindWindowEx(hwndWindow,0,vbNullString,sWindowButton)
If hwndButton Then Msgbox "Got the button, Activating the window and clicking the button" 'Activate the window Extern.SetActiveWindow hwndWindow 'Post the BN_CLICK message twice. We are doing it twice as 'sometimes the first message is missed Extern.PostMessage hwndButton,BN_CLICK, 0, 0 Extern.PostMessage hwndButton,BN_CLICK, 0, 0 Else Msgbox "Cannot find the button" End If Else Msgbox "Cannot find the window" End If |
Method2: Write the code in VBS file and invoke itfrom QTP asynchronously using WSH Shell object.
‘Code in VBSà C:\AutoClick.vbs Const micLong = 3 Const micString = 8 Const micByRef = 32768
Set Extern = createObject("Mercury.ExternObj")
Extern.Declare micLong,"FindWindow","user32.dll","FindWindowA", _ micString,micString Extern.Declare micLong,"FindWindowEx","user32.dll","FindWindowExA", _ micLong,micLong,micString,micString Extern.Declare micLong,"PostMessage","user32.dll","PostMessageA", _ micLong,micLong,micLong,micRef+micLong Extern.Declare micLong,"SetActiveWindow","user32.dll","SetActiveWindow", _ micLong
'Constant for the Click event message for a button Private Const BN_CLICK = 245
'Note the window and button name are case sensitive 'Get the WindowName and Button Name from the arguments 'specifi sWindowName = WScript.Arguments(0) sWindowButton = WScript.Arguments(1)
'Run the Script until the window is clicked atleast once While Not AutoClickButton(sWindowName,sWindowButton) Wend
Set Extern = Nothing
Private Function AutoClickButton(ByVal sWindowName, ByVal sWindowButton) AutoClickButton = False
hwndWindow = Extern.FindWindow(vbNullString, sWindowName) If hwndWindow Then hwndButton = Extern.FindWindowEx(hwndWindow, 0, vbNullString, sWindowButton) If hwndButton Then Extern.SetActiveWindow hwndWindow Extern.PostMessage hwndButton, BN_CLICK, 0, 0 Extern.PostMessage hwndButton, BN_CLICK, 0, 0 AutoClickButton = True End If End If End Function |
‘Code in QTP Set WshShell = CreateObject("WScript.Shell") sWindowName = """" & "Test Window" & """" sWindowButton = """" & "OK" & """"
Return = WshShell.Run("C:\AutoClick.vbs "& sWindowName & " " & sWindowButton, 1, False )
‘Code that may be pop up or message dialog……..
Set WshShell = Nothing |