maniootek Posted April 9 Share Posted April 9 I am playing with ComboBox control in Connect to Server window in Microsoft SQL Server Management Studio application for Windows 10. I used UI Spy on that control and I can read all values INSIDE that ComboBox (Database Engine, Analysis Services, Reporting Servcies, Integration Services) but when I try to read it with AutoIt then I got no infomation about it, I can't read it. Any solution? I am also wondering how to change the value on that ComboBox. Should I click on that button (with small arrow facing down on the right) to show all options and then read new elements via UI Automation annd then click/invoke on specified option or maybe there is better and faster way to do it? expandcollapse popup#include "CUIAutomation2.au3" MSSMS_ServerTypeCheckbox_Test() Func MSSMS_ServerTypeCheckbox_Test() ;UI Automation object initiation Global $UIA_oUIAutomation = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation) If Not IsObj($UIA_oUIAutomation) Or @error Then Exit MsgBox(0, 0, "Error during creating $UIA_oUIAutomation object.") Local $handle = WinGetHandle("Microsoft SQL Server Management Studio") If @error Then Exit MsgBox(0, 0, "window not found") Local $ae_MSSM_ConnectToServer = UIA_GetAeFromHandle($handle) If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_MSSM_ConnectToServer") Local $ae_Window_Connect = UIA_GetAeFirstFromCondition($ae_MSSM_ConnectToServer, "AutomationID", "ConnectionDialog") If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_Window_Connect") Local $ae_Pane1 = UIA_GetAeFirstFromCondition($ae_Window_Connect, "AutomationID", "simpleView") If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_Pane1") Local $ae_Pane2 = UIA_GetAeFirstFromCondition($ae_Pane1, "AutomationID", "loginHolder") If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_Pane2") Local $ae_Pane3 = UIA_GetAeFirstFromCondition($ae_Pane2, "AutomationID", "LoginControl") If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_Pane3") Local $ae_ComboBox1 = UIA_GetAeFirstFromCondition($ae_Pane3, "AutomationID", "comboBoxServerType") If @error Then Exit MsgBox(0, 0, "UIA_GetAeFromHandle() error" & @CRLF & "$ae_ComboBox1") MsgBox(0, 0, "ComboBox1" & @CRLF & _ "Name: " & UIA_GetAeCurrentPropertyValue($ae_ComboBox1, "Name") & @CRLF & _ "ControlType : " & UIA_GetAeCurrentPropertyValue($ae_ComboBox1, "ControlType") & @CRLF & _ "AutomationID : " & UIA_GetAeCurrentPropertyValue($ae_ComboBox1, "AutomationID")) EndFunc ;==>MSSMS_ServerTypeCheckbox_Test Func UIA_GetAeFromHandle($handle) If Not IsObj($UIA_oUIAutomation) Then Return SetError(1) If Not WinExists($handle) Then Return SetError(2) Local $winPointer $UIA_oUIAutomation.ElementFromHandle($handle, $winPointer) Local $aeResult = ObjCreateInterface($winPointer, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($aeResult) Then Return SetError(3) Return $aeResult EndFunc ;==>UIA_GetAeFromHandle Func UIA_GetAeFirstFromCondition($oAe, $PropertyID, $Value) ;module UIA_PropertyIds ; chyba nie działa jeżeli jest tylko jeden child, wtedy użyć UIA_GetAeFirstChild() If Not IsObj($UIA_oUIAutomation) Then Return SetError(1) If Not IsObj($oAe) Then Return SetError(2) $PropertyID = UIA_PropertyNameToID($PropertyID) $Value = UIA_ControlTypeNameToID($Value) Local $targetPointer, $propCondInterfaceObj $UIA_oUIAutomation.CreatePropertyCondition($PropertyID, $Value, $propCondInterfaceObj) $oAe.FindFirst($TreeScope_Descendants, $propCondInterfaceObj, $targetPointer) Local $aeResult = ObjCreateInterface($targetPointer, $sIID_IUIAutomationElement, $dtagIUIAutomationElement) If Not IsObj($aeResult) Then Return SetError(3) Return $aeResult EndFunc ;==>UIA_GetAeFirstFromCondition Func UIA_PropertyNameToID($PropertyName) Local $PropertyID = "" Switch $PropertyName Case "ControlType" $PropertyID = $UIA_ControlTypePropertyId Case "AutomationID" $PropertyID = $UIA_AutomationIdPropertyId Case "Name" $PropertyID = $UIA_NamePropertyId Case "ClassName" $PropertyID = $UIA_ClassNamePropertyId Case "BoundingRectangle" $PropertyID = $UIA_BoundingRectanglePropertyId Case "Handle" $PropertyID = $UIA_NativeWindowHandlePropertyId ;use Hex() or Hwnd() after Case "AccessKey" $PropertyID = $UIA_AccessKeyPropertyId Case "Value" $PropertyID = $UIA_LegacyIAccessibleValuePropertyId Case "Value.Value" $PropertyID = $UIA_ValueValuePropertyId Case "IsInvokePatternAvailable" $PropertyID = $UIA_IsInvokePatternAvailablePropertyId Case "IsKeyboardFocusable" $PropertyID = $UIA_IsKeyboardFocusablePropertyId Case "HasKeyboardFocus" $PropertyID = $UIA_HasKeyboardFocusPropertyId EndSwitch If $PropertyID <> "" Then Return $PropertyID SetError(1) Return $PropertyName EndFunc ;==>UIA_PropertyNameToID Func UIA_GetAeCurrentPropertyValue($oAe, $PropertyID) If Not IsObj($UIA_oUIAutomation) Then Return SetError(1) If Not IsObj($oAe) Then Return SetError(2) $PropertyID = UIA_PropertyNameToID($PropertyID) Local $tVal $oAe.GetCurrentPropertyValue($PropertyID, $tVal) If Not IsArray($tVal) Then Return $tVal Local $tStr = $tVal[0] For $i = 1 To UBound($tVal) - 1 $tStr &= "; " & $tVal[$i] Next Return $tStr EndFunc ;==>UIA_GetAeCurrentPropertyValue Func UIA_ControlTypeNameToID($ControlTypeName) Local $ControlTypeID = "" Switch $ControlTypeName ;UIA_ControlTypeIds Case "Edit" $ControlTypeID = $UIA_EditControlTypeId Case "Button" $ControlTypeID = $UIA_ButtonControlTypeId Case "Pane" $ControlTypeID = $UIA_PaneControlTypeId Case "SplitButton" $ControlTypeID = $UIA_SplitButtonControlTypeId Case "Toolbar" $ControlTypeID = $UIA_ToolBarControlTypeId Case "List" $ControlTypeID = $UIA_ListControlTypeId Case "ListItem" $ControlTypeID = $UIA_MenuControlTypeId Case "Hyperlink" $ControlTypeID = $UIA_HyperlinkControlTypeId EndSwitch If $ControlTypeID <> "" Then Return $ControlTypeID SetError(1) Return $ControlTypeName EndFunc ;==>UIA_ControlTypeNameToID Link to comment Share on other sites More sharing options...
Solution Andreik Posted April 9 Solution Share Posted April 9 (edited) #include <GuiComboBox.au3> WinWait('Connect to Server') $hCtrl = ControlGetHandle('Connect to Server', '', '[REGEXPCLASS:WindowsForms10\.COMBOBOX\.app(.*?)_ad1; INSTANCE:1]') $aItem = _GUICtrlComboBox_GetListArray($hCtrl) If IsArray($aItem) Then For $Index = 1 To $aItem[0] ConsoleWrite($aItem[$Index] & @CRLF) Next EndIf ; Select new string in combo _GUICtrlComboBox_SelectString($hCtrl, 'Analysis Services') Tested with SSMS 20.0.70.0 Edited April 9 by Andreik maniootek 1 Link to comment Share on other sites More sharing options...
maniootek Posted April 9 Author Share Posted April 9 1 minute ago, Andreik said: #include <GuiComboBox.au3> WinWait('Connect to Server') $hCtrl = ControlGetHandle('Connect to Server', '', '[REGEXPCLASS:WindowsForms10\.COMBOBOX\.app(.*?)_ad1]') $aItem = _GUICtrlComboBox_GetListArray($hCtrl) If IsArray($aItem) Then For $Index = 1 To $aItem[0] ConsoleWrite($aItem[$Index] & @CRLF) Next EndIf ; Select new string in combo _GUICtrlComboBox_SelectString($hCtrl, 'Analysis Services') Tested with SSMS 20.0.70.0 no way 😅 Link to comment Share on other sites More sharing options...
Andreik Posted April 9 Share Posted April 9 Added instance in the code above for the sake of clarity, just in case you will target other combobox than Server type. Link to comment Share on other sites More sharing options...
Hello_World Posted April 9 Share Posted April 9 Do I understand correctly? That this code sets the appropriate text in the control but it doesn't necessarily make a selection? The issue is that the text in the next combobox depends on the value chosen in the first control, and while this code does set the text in the Server type to the chosen one, it doesn't actually make the selection, hence the subsequent combobox cannot choose the appropriate text as it doesn't change to match the selection from the first one. Link to comment Share on other sites More sharing options...
Andreik Posted April 9 Share Posted April 9 You can make a selection with _GUICtrlComboBox_SetCurSel() but this doesn't mean that the UI will change because this is done internally by SSMS. Basically if you want to see the change in UI you can do something like this: #include <GuiComboBox.au3> Local $hWin = WinWait('Connect to Server') Local $hCtrl = ControlGetHandle('Connect to Server', '', '[REGEXPCLASS:WindowsForms10\.COMBOBOX\.app(.*?)_ad1; INSTANCE:1]') Local $aItem = _GUICtrlComboBox_GetListArray($hCtrl) Local $sText If IsArray($aItem) Then For $Index = 1 To $aItem[0] ControlSend($hWin, '', $hCtrl, '{DOWN}') _GUICtrlComboBox_GetLBText($hCtrl, _GUICtrlComboBox_GetCurSel($hCtrl), $sText) If $sText = 'Analysis Services' Then ExitLoop Next EndIf Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now