Birch Posted October 13, 2006 Share Posted October 13, 2006 Is it possible to turn pointers to IDispatch interfaces returned from a DLL call (particularly the MSAA AccessibleObjectFromWindow call) into Objects, at least as far as AutoIT is concerned? Or am I going to have to wrap this in a COM object so that I can instantiate this using ObjCreate? Or, am I just missing something that should be obvious? Here's the code I've got so far. Ignore the fact that I'm targeting Outlook for right now. That's just a stand-in for the app I'm eventually going to have to automate. Global Const $OBJID_WINDOW = 0x00000000 $IID_IDispatch = DllStructCreate("int;short;short;byte[8]") ; IID_IDispatch = {00020400-0000-0000-C000-000000000046} DllStructSetData($IID_IDispatch, 1,0x00020400) DllStructSetData($IID_IDispatch, 2, 0) DllStructSetData($IID_IDispatch, 3, 0) DllStructSetData($IID_IDispatch, 4, 192, 1); dec 192 = hex C0 DllStructSetData($IID_IDispatch, 4, 0, 2) DllStructSetData($IID_IDispatch, 4, 0, 3) DllStructSetData($IID_IDispatch, 4, 0, 4) DllStructSetData($IID_IDispatch, 4, 0, 5) DllStructSetData($IID_IDispatch, 4, 0, 6) DllStructSetData($IID_IDispatch, 4, 0, 7) DllStructSetData($IID_IDispatch, 4, 70, 8);dec 70 = hex 46 $hWnd = ControlGetHandle("Inbox - Microsoft Outlook","","NetUIHWND1") $AccObjPtr = DllStructCreate("ptr") $result = DllCall("oleacc.dll", "long", "AccessibleObjectFromWindow", "hwnd", $hWnd, "long", $OBJID_WINDOW, "ptr", DllStructGetPtr($IID_IDispatch), "ptr", DllStructGetPtr($AccObjPtr)) $AccObj=DllStructGetData($AccObjPtr,1) if IsObj($AccObj) then MsgBox(4096, "Success", "This is an object") else MsgBox(4096, "Sadness", "This is not an object: " & $AccObj & "; Dll call returned " & Hex($result[0])) endif ;The following does not work, $AccObj is not an obj ;$accName = $AccObj.accName ;MsgBox(4096, "Maybe", "Does this work? " & $accName) If this is something I'm going to have to wrap, does anybody know of an existant wrapping of this? I'd hate to go through all that if somebody else has already published a wrapper. Thanks in advance! CVC Link to comment Share on other sites More sharing options...
Valik Posted October 13, 2006 Share Posted October 13, 2006 (edited) There are two undocumented types "idispatch" which converts between IDispatch* and an AutoIt variable (It will turn an IDispatch pointer into a COM-enabled AutoIt variable). I think there is also "idispatch_ptr" which is treated as IDispatch**.Edit: These types are available with DllCall() only, not via DllStructCreate(). And for now they aren't really supported so basically you're on your own getting it to work. Edited October 13, 2006 by Valik Link to comment Share on other sites More sharing options...
Birch Posted October 14, 2006 Author Share Posted October 14, 2006 Thanks! That got me quite a bit farther. At the risk of documenting things, here's what the DllCall code looks like: $result = DllCall("oleacc.dll", "long", "AccessibleObjectFromWindow", "hwnd", $hWnd, "long", $OBJID_WINDOW, "ptr", DllStructGetPtr($IID_IAccessible), "idispatch_ptr", "") $AccObjPtr = $result[4] Also, for anybody who drops by looking for MSAA stuff, none of that will work without a call to CoInitialize first, apparently, so the code ultimately winds up looking like this: expandcollapse popupGlobal Const $OBJID_WINDOW = 0x00000000 $IID_IAccessible = DllStructCreate("int;short;short;byte[8]") ;Define the GUID for the IAccessible interface. ;{618736E0-3C3D-11CF-810C-00AA00389B71} DllStructSetData($IID_IAccessible, 1,0x618736E0) DllStructSetData($IID_IAccessible, 2, 0x3C3D) DllStructSetData($IID_IAccessible, 3, 0x11CF) DllStructSetData($IID_IAccessible, 4, 0x81, 1) DllStructSetData($IID_IAccessible, 4, 0xC, 2) DllStructSetData($IID_IAccessible, 4, 0, 3) DllStructSetData($IID_IAccessible, 4, 0xAA, 4) DllStructSetData($IID_IAccessible, 4, 0, 5) DllStructSetData($IID_IAccessible, 4, 0x38, 6) DllStructSetData($IID_IAccessible, 4, 0x9B, 7) DllStructSetData($IID_IAccessible, 4, 0x71, 8) $hWnd = ControlGetHandle("Inbox - Microsoft Outlook","","NetUIHWND1") $COInitResult = DllCall("ole32.dll", "long", "CoInitialize", "ptr", "") $result = DllCall("oleacc.dll", "long", "AccessibleObjectFromWindow", "hwnd", $hWnd, "long", $OBJID_WINDOW, "ptr", DllStructGetPtr($IID_IAccessible), "idispatch_ptr", "") $AccObjPtr = $result[4] if True <> IsObj($AccObjPtr) then ;0x80070057 => invalid argument MsgBox(4096, "Sadness", "This is not an object: " & $AccObjPtr & "; Dll call returned " & Hex($result[0])) endif $oMyError = ObjEvent("AutoIt.Error","MyErrFunc"); Install a custom error handler $accCount = $AccObjPtr.accChildCount $accName = $AccObjPtr.accName() MsgBox(4096, "Maybe", "This works " & $accName & " Child count: " & $accCount) $COInitResult = DllCall("ole32.dll", "long", "CoUnInitialize") ; This is my custom error handler Func MyErrFunc() $HexNumber=hex($oMyError.number,8) Msgbox(0,"","We intercepted a COM Error !" & @CRLF & _ "Number is: " & $HexNumber & @CRLF & _ "Windescription is: " & $oMyError.windescription ) SetError(1); something to check for when this function returns Endfunc Now all I need to do is figure out why $accChild = $AccObjPtr.accChild(1) keeps returning 0x80020009 - "the parameter is incorrect" I'll raise that in a different thread, though Link to comment Share on other sites More sharing options...
NathanR Posted May 22, 2007 Share Posted May 22, 2007 I copied and pasted the code and it causes AutoIt to crash with an access violation. Any ideas? I am running version 3.2.4.6. Link to comment Share on other sites More sharing options...
Birch Posted June 15, 2007 Author Share Posted June 15, 2007 I copied and pasted the code and it causes AutoIt to crash with an access violation. Any ideas? I am running version 3.2.4.6.Could you be more specific about which line was causing AutoIT to crash, and any information returned by AutoIT or the system as part of the crash? Link to comment Share on other sites More sharing options...
Birch Posted July 16, 2007 Author Share Posted July 16, 2007 Looking into this, it seems that it's the "idispatch_ptr" in the DllCall statement that causes things to break. Is there any way to get an undocumented, unsupported feature fixed? 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