jbc1 Posted August 5, 2009 Share Posted August 5, 2009 (edited) Hi all, I have a collection of AutoIT scripts which I use to run build sanity checks on my builds. The dialogs I am testing are basically HTML code contained within a custom HTML container. I find the IE functions very useful as I can click buttons, wait for certain elements to appear etc. For each dialog I am testing, I get the HTML source on the fly like this: (All the HTML is within an 'Internet Explorer_Server' Object) #include <ie.au3> #include "functions.au3" $WindowTitle = "My App Window Title" $Win_hWnd = WinGetHandle($WindowTitle) ; WinActivate($Win_hWnd) $IE_hWnd = ControlGetHandle($Win_hWnd,"","[Class:Internet Explorer_Server;Instance:1]") $o_IE = _ObjGetFromHWND($IE_hWnd) If IsObj($o_IE) Then $ieHTML = _IEDocReadHTML($o_IE) Else MsgBos(1, "ERROR", "o_IE is not an Object" EndIf The attached file, 'functions.au3' contains the functions I use to get the HTML source, I did not write these, but got them on this forum a while back. My problem is that now my code does not work on new builds, so I need to troubleshoot, but I don't know how these functions work, especially, '_ObjGetFromHWND'. I keep getting the "o_IE is not an Object" message. Can anybody explain how these functions work, and if I may need to change anything in them in order for my code to work ? I especially don't understand this section of '_ObjGetFromHWND' $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) Thanks. jbc1functions.au3 Edited August 5, 2009 by jbc1 Link to comment Share on other sites More sharing options...
Authenticity Posted August 5, 2009 Share Posted August 5, 2009 I think that this GUID is hust the IID_Accessible GUID. Try to change this line in the _ObjGetFromHWND() function: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch_ptr", "") to: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch*", "") You can search the example forum, trancexx have posted a nice topic with samples about the subject. >_< Link to comment Share on other sites More sharing options...
jbc1 Posted August 5, 2009 Author Share Posted August 5, 2009 I think that this GUID is hust the IID_Accessible GUID. Try to change this line in the _ObjGetFromHWND() function: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch_ptr", "") to: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch*", "") You can search the example forum, trancexx have posted a nice topic with samples about the subject. >_< This made no differance, and I must say I actually lost faith in the search on this forum a while back!! Thanks for your response! Link to comment Share on other sites More sharing options...
Authenticity Posted August 5, 2009 Share Posted August 5, 2009 Too bad because it took me less than a minute to find it: Link Link to comment Share on other sites More sharing options...
jbc1 Posted August 5, 2009 Author Share Posted August 5, 2009 Too bad because it took me less than a minute to find it: LinkIt's easy when you know how I suppose >_< I think this may be different to what I am looking for. To re-iterate, I need to get the text behind an "Internet Explore_Server" Object. My code worked before, but now it doesn't, I was just wondering if the section I mentioned in my first post from '_ObjGetFromHWND' has something specific to do with the window. Link to comment Share on other sites More sharing options...
Authenticity Posted August 5, 2009 Share Posted August 5, 2009 (edited) Heh, I hope it'll work for you. The problem was with SendMessageTimeOut and the unknown type idispatch_ptr which should be idispatch*. functions.au3:expandcollapse popup#include <WinAPI.au3> Func _RegisterWindowMessage($sMsg) Local $aRet = DllCall("user32.dll", "int", "RegisterWindowMessage", "str", $sMsg) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc Func _SendMessageTimeout($hWnd, $msg, $wParam, $lParam, $nFlags, $nTimeout, ByRef $vOut, $r = 0, $t1 = "int", $t2 = "int") Local $aRet = DllCall("user32.dll", "long", "SendMessageTimeout", "hwnd", $hWnd, "int", $msg, $t1, $wParam, $t2, $lParam, "int", $nFlags, "int", $nTimeout, "int*", "") If @error Then $vOut = 0 Return SetError(@error, @extended, 0) EndIf $vOut = $aRet[7] If $r >= 0 And $r <= 4 Then Return $aRet[$r] Return $aRet EndFunc Func _ObjGetFromHWND(ByRef $hWin) DLLCall("ole32.dll","int","CoInitialize","ptr",0) If @error Then Return SetError(@error,@extended,0) Local Const $WM_HTML_GETOBJECT = _RegisterWindowMessage("WM_HTML_GETOBJECT") If @error Then Return SetError(@error,@extended,0) Local Const $SMTO_ABORTIFHUNG = 0x0002 Local $lResult, $typUUID, $aRet, $oIE _SendMessageTimeout($hWin, $WM_HTML_GETOBJECT, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lResult) If @error Then Return SetError(@error,@extended,0) $typUUID = _WinAPI_GUIDFromString('{626FC520-A41E-11cf-A731-00A0C9082637}') $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch*", "") If @error Then Return SetError(@error,@extended,0) ; If Not IsObj($aRet[4]) Then Return SetError(1,@extended,0) $oIE = $aRet[4].Script() ; $oIE is now a valid IDispatch object ;Return $oIE.document.parentwindow Return $oIE EndFunctest.au3:#include "functions.au3" ShellExecute('iexplore.exe', 'www.google.com') WinWaitActive('[CLASS:IEFrame]') $hWnd = WinGetHandle('[CLASS:IEFrame]') $IE_hWnd = 0 Do $IE_hWnd = ControlGetHandle($hWnd, '', 'Internet Explorer_Server1') Sleep(200) Until $IE_hWnd Sleep(2000) $oIE = _ObjGetFromHWND($IE_hWnd) $oIE.navigate('http://www.autoitscript.com')Edit: By the way, the GUID is of IID_IHTMLDocument GUID. Edited August 5, 2009 by Authenticity Link to comment Share on other sites More sharing options...
jbc1 Posted August 5, 2009 Author Share Posted August 5, 2009 Unfortuntely when I try to adapt this to the application I need to get the source of, I get the error message: 'The requested action with this Object has failed' $typUUID = _WinAPI_GUIDFromString('{626FC520-A41E-11cf-A731-00A0C9082637}') Is the above libe specifc to the application I am testing? Link to comment Share on other sites More sharing options...
Authenticity Posted August 5, 2009 Share Posted August 5, 2009 Well, it's working when tested so I guess that one of the parameters or hwnd's is not correct. You can revert to the initial functions.au3 but the two things you need to change are as followed: Change in _SendMessageTimeOut: ; From: Local $aRet = DllCall("user32.dll", "long", "SendMessageTimeout", "hwnd", $hWnd, "int", $msg, $t1, $wParam, $t2, $lParam, "int", $nFlags, "int", $nTimeout, "int_ptr", "") ; To: Local $aRet = DllCall("user32.dll", "long", "SendMessageTimeout", "hwnd", $hWnd, "int", $msg, $t1, $wParam, $t2, $lParam, "int", $nFlags, "int", $nTimeout, "int*", "") and in _ObjGetFromHWND: ; From: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch_ptr", "") ; To: $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch*", "") The rest of the code don't use any of the WinAPI.au3 library functions so it can be removed. Can you post the relevant code that is not succeeding. Before you can spot the faulting parameter(s) you should check if all the window handles are correct and contain a valid handle value, it can be one of the problem that the function fails. Link to comment Share on other sites More sharing options...
trancexx Posted August 5, 2009 Share Posted August 5, 2009 (edited) I'm not MVP but...When working with "idispatch" type I encountered this function (_IEControlGetObjFromHWND), and actually dismantled it completely (it's called abstraction). At the end it lead me to the conclusion that the function could be written differently. I did manage to find the source of that function - yes it's Microsoft's suggestion. Of course that doesn't mean that it can't be done better.I think that function should look like this:expandcollapse popupFunc _IEControlGetObjFromHWND($hWin) Local $aCall = DllCall("user32.dll", "dword", "RegisterWindowMessageW", "wstr", "WM_HTML_GETOBJECT") If @error Or Not $aCall[0] Then Return SetError(1, 0, "") EndIf Local Const $WM_HTML_GETOBJECT = $aCall[0] $aCall = DllCall("user32.dll", "lresult", "SendMessageW", _ "hwnd", $hWin, _ "dword", $WM_HTML_GETOBJECT, _ "wparam", 0, _ "lparam", 0) Local $lResult = $aCall[0] Local $tUUID = _WinAPI_GUIDFromString("{626FC520-A41E-11CF-A731-00A0C9082637}") ; IID_IHTMLDocument DllCall("ole32.dll", "int", "CoInitializeEx", "ptr", 0, "dword", 2) ;COINIT_APARTMENTTHREADED $aCall = DllCall("oleacc.dll", "dword", "ObjectFromLresult", _ "lresult", $lResult, _ "ptr", DllStructGetPtr($tUUID), _ "wparam", 0, _ "idispatch*", 0) If IsObj($aCall[4]) Then Local $oIE = $aCall[4].Script() ; $oIE is now a valid IDispatch object Return $oIE.document.parentwindow Else Return SetError(1, 0, 0) EndIf EndFunc ;==>IEControlGetObjFromHWNDFocus is important and error checking is generally essential, if that means anything to anyone.edit: s Edited August 5, 2009 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
rv77 Posted February 7, 2013 Share Posted February 7, 2013 I'm trying to adapt this code to make it work (i.e. return the object by handle) for a MSFlexGrid object. For now I tried to change it to: expandcollapse popup#include Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc") ; Here goes your code ; User's COM error function. Will be called if COM error occurs Func _ErrFunc() ; Do anything here. ConsoleWrite("err.number is: " & @TAB & $oError.number & @CRLF & _ "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ "err.description is: " & @TAB & $oError.description & @CRLF & _ "err.source is: " & @TAB & $oError.source & @CRLF & _ "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ "err.retcode is: " & @TAB & $oError.retcode & @CRLF & @CRLF) EndFunc ;==>_ErrFunc Func _RegisterWindowMessage($sMsg) Local $aRet = DllCall("user32.dll", "int", "RegisterWindowMessage", "str", $sMsg) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc Func _SendMessageTimeout($hWnd, $msg, $wParam, $lParam, $nFlags, $nTimeout, ByRef $vOut, $r = 0, $t1 = "int", $t2 = "int") Local $aRet = DllCall("user32.dll", "long", "SendMessageTimeout", "hwnd", $hWnd, "int", $msg, $t1, $wParam, $t2, $lParam, "int", $nFlags, "int", $nTimeout, "int*", "") If @error Then $vOut = 0 Return SetError(@error, @extended, 0) EndIf $vOut = $aRet[7] If $r >= 0 And $r <= 4 Then Return $aRet[$r] Return $aRet EndFunc Func _ObjGetFromHWND(ByRef $hWin) DLLCall("ole32.dll","int","CoInitialize","ptr",0) If @error Then Return SetError(@error,@extended,0) ;changed from ;Local Const $WM_HTML_GETOBJECT = _RegisterWindowMessage("WM_HTML_GETOBJECT") ;...to Local Const $WM_HTML_GETOBJECT = _RegisterWindowMessage("WM_GETOBJECT") If @error Then Return SetError(@error,@extended,0) Local Const $SMTO_ABORTIFHUNG = 0x0002 Local $lResult, $typUUID, $aRet, $oIE _SendMessageTimeout($hWin, $WM_HTML_GETOBJECT, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lResult) If @error Then Return SetError(@error,@extended,0) ;changed from ;$typUUID = _WinAPI_GUIDFromString('{626FC520-A41E-11cf-A731-00A0C9082637}') ;...to $typUUID = _WinAPI_GUIDFromString('{5F4DF280-531B-11CF-91F6-C2863C385E30}') $aRet = DllCall("oleacc.dll", "int", "ObjectFromLresult", "int", $lResult, _ "ptr", DLLStructGetPtr($typUUID), "int", 0, "idispatch*", "") If @error Then Return SetError(@error,@extended,0) ; If Not IsObj($aRet[4]) Then Return SetError(1,@extended,0) ;this fails with the error below - Script() is obviously wrong but have no clue what to put instead $oIE = $aRet[4].Script() ; $oIE is now a valid IDispatch object ;Return $oIE.document.parentwindow Return $oIE EndFunc err.number is: 2 err.windescription: Not an Object type err.description is: err.source is: err.helpfile is: err.helpcontext is: 0 err.lastdllerror is: 127 err.scriptline is: 56 err.retcode is: 0 Can anyone help? 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