Sign in to follow this  
Followers 0

AccessibleObjectFromWindow failing to return IDispatch

8 posts in this topic

#1 ·  Posted (edited)


Based on this thread, I am attempting to retrieve a control's Accessible object. The ultimate goal here is to provide the ability to utilize Active Accessibility for Test Automation purposes without having to rely on an external DLL to wrap around oleacc.dll.

In the mock-up below, I am expecting $result[4] to be a reference to an IDispatch object. However, it is returning empty. Does anyone see the err of my ways, and if so, could provide some advisement? Thanks in advance.

Global Const $OBJID_WINDOW = 0x00000000

; Open Calculator and obtain handle for the '2' button
Dim $hWnd = ControlGetHandle("Calculator", "", "[TEXT:2]")

; Define the IAccessible GUID
Dim $IID_IAccessible = DllStructCreate("int;short;short;byte[8]")
DllStructSetData($IID_IAccessible, 1, 0x626FC520)
DllStructSetData($IID_IAccessible, 2, 0xA41E)
DllStructSetData($IID_IAccessible, 3, 0x11CF)
DllStructSetData($IID_IAccessible, 4, 0xA7, 1)
DllStructSetData($IID_IAccessible, 4, 0x31, 2)
DllStructSetData($IID_IAccessible, 4, 0x0, 3)
DllStructSetData($IID_IAccessible, 4, 0xA0, 4)
DllStructSetData($IID_IAccessible, 4, 0xC9, 5)
DllStructSetData($IID_IAccessible, 4, 0x8, 6)
DllStructSetData($IID_IAccessible, 4, 0x26, 7)
DllStructSetData($IID_IAccessible, 4, 0x37, 8)

; Call to AccessibleObjectFromWindow in the hopes of receiving a valid IDispatch object
DllCall("ole32.dll", "long", "CoInitialize", "ptr", "")
Dim $result = DllCall("oleacc.dll", "long", "AccessibleObjectFromWindow", "hwnd", $hWnd, "long", _
        $OBJID_WINDOW, "ptr", DllStructGetPtr($IID_IAccessible), "idispatch*", 0)

; Post the test result to the console
Dim $actualResult = IsObj($result[4])
ConsoleWrite(StringFormat("Expected: 1\tActual: %s", $actualResult) & @CRLF)

; Cleanup

+>14:07:13 Starting AutoIt3Wrapper v. Environment(Language:0409 Keyboard:00000409 OS:WIN_XP/Service Pack 2 CPU:X86 ANSI)

>Running AU3Check ( from:C:\Program Files\AutoIt3

+>14:07:13 AU3Check ended.rc:0

>Running:(\Program Files\AutoIt3\autoit3.exe "C:\Documents and Settings\fisherz\Desktop\test.au3"

Expected: 1 Actual: 0

+>14:07:13 AutoIT3.exe ended.rc:0

+>14:07:15 AutoIt3Wrapper Finished

>Exit code: 0 Time: 2.255

EDIT: Wrong variable name provided. Edited by zfisherdrums

Share this post

Link to post
Share on other sites

In IE.AU3 there is code like below. Maybe that solves the problem

; Function Name:    __IEControlGetObjFromHWND()
; Description:      Returns a COM Object Window reference to an embebedded Webbrowser control
; Parameter(s):     $hWin       - HWND of a Internet Explorer_Server1 control obtained for example:
;                   $hwnd = ControlGetHandle("MyApp","","Internet Explorer_Server1")
; Requirement(s):   Windows XP, Windows 2003 or higher.
;                   Windows 2000; Windows 98; Windows ME; Windows NT may install the
;                   Microsoft Active Accessibility 2.0 Redistributable:
; Return Value(s):  On Success  - Returns DOM Window object
;                  On Failure   - 0  and sets @ERROR = 1
; Author(s):        Larry with thanks to Valik
Func __IEControlGetObjFromHWND(ByRef $hWin)
    DllCall("ole32.dll", "int", "CoInitialize", "ptr", 0)
    Local Const $WM_HTML_GETOBJECT = __IERegisterWindowMessage("WM_HTML_GETOBJECT")
    Local Const $SMTO_ABORTIFHUNG = 0x0002
    Local $lResult, $typUUID, $aRet, $oIE
    __IESendMessageTimeout($hWin, $WM_HTML_GETOBJECT, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lResult)
    $typUUID = DllStructCreate("int;short;short;byte[8]")
    DllStructSetData($typUUID, 1, 0x626FC520)
    DllStructSetData($typUUID, 2, 0xA41E)
    DllStructSetData($typUUID, 3, 0x11CF)
    DllStructSetData($typUUID, 4, 0xA7, 1)
    DllStructSetData($typUUID, 4, 0x31, 2)
    DllStructSetData($typUUID, 4, 0x0, 3)
    DllStructSetData($typUUID, 4, 0xA0, 4)
    DllStructSetData($typUUID, 4, 0xC9, 5)
    DllStructSetData($typUUID, 4, 0x8, 6)
    DllStructSetData($typUUID, 4, 0x26, 7)
    DllStructSetData($typUUID, 4, 0x37, 8)

    $aRet = DllCall("oleacc.dll", "long", "ObjectFromLresult", "lresult", $lResult, "ptr", DllStructGetPtr($typUUID), _
            "wparam", 0, "idispatch*", 0)

    If IsObj($aRet[4]) Then
        $oIE = $aRet[4] .Script()
    ; $oIE is now a valid IDispatch object
        Return $oIE.document.parentwindow
        Return 0
EndFunc  ;==>__IEControlGetObjFromHWND

Share this post

Link to post
Share on other sites

I think AutoIt can't use an IAccessible object, just IDispatch. So you would have to use IID_Dispatch to get the object.

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post

Link to post
Share on other sites

#6 ·  Posted (edited)

No dice on any of the above.

I had already tried the IE.au3 method, but unfortunately, the WM_HTML_GETOBJECT message is not what I need when testing a Non-web based application. I attempted to use the same methodology using WM_GETOBJECT, but was not able to retrieve a valid IDispatch object from "ObjectFromLresult". If I recall correctly, one upstream problems was getting back a valid $lResult from my SendMessage() call.

Anyhoo, I wrapped up some MsAA functionality in VB6 and created a DLL. It is based on source code found here. Also, I used Fritsche's source code as a point of reference - although the two code bases appear very similar.

If you're flexible with your solution, you could write your script in VBA. I ported this example into VBA with little change and received the desired output. As of today, I've had no success in porting this to AutoIt. c'est la vie.

Declare Function AccessibleObjectFromPoint& Lib "oleacc" (ByVal x&, ByVal y&, ppoleAcc As Object, pvarElement As Variant)
Declare Function GetRoleText& Lib "oleacc" Alias "GetRoleTextA" (ByVal Role&, ByVal Text$, ByVal Size&)
Declare Function GetStateText& Lib "oleacc" Alias "GetStateTextA" (ByVal State&, ByVal Text$, ByVal Size&)

    x As Integer
    y As Integer
End Type

Public Sub Test()
    Dim objAccessible As Object, pt As POINTAPI, dl&, sName$, sValue$
    Dim v As Variant, vState As Variant, sRole As Variant
    pt.x = 251   '<---these coordinates should be obtained via a call to WinGetPos() [AutoItX.dll]
    pt.y = 293
    dl = AccessibleObjectFromPoint(pt.x, pt.y, objAccessible, v)
    sName = objAccessible.accName(v)
    sValue = Trim$(objAccessible.accValue(v))
    vState = objAccessible.accState(v)
    sRole = objAccessible.accRole(v)
    Debug.Print (sName)
    Debug.Print (sValue)
    Debug.Print (vState)
    Debug.Print (sRole)
End Sub

Edit: I PORTED the example, not POSTED; big difference!

Edited by zfisherdrums

Share this post

Link to post
Share on other sites

#8 ·  Posted (edited)

sry for asking for help in ur topic zfisherdrums

though im still lost

im trying to get the Value of an object and i have the source code of a prog that does this .BAS

if u have any experience in BASIC we can try working on that

Edit : and btw i guess AccessibleObjectFromPoint is not what im looking for as far as i know it gives the value in an object which the mouse is over or with the pos defined but i need to specify the object name like "history" and still lost though

Edited by yehia

Share this post

Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
Followers 0