Aditya Posted November 1, 2009 Posted November 1, 2009 First of all I am not a windows programmer, so some of my terminology might be off. So bear with me. I am trying to translate IE.au3 UDF in to Perl - specifically _IEAttach function. I got as far as to get the HWND of an embedded IE in Perl. The code is pretty simple: use strict; use warnings; use Win32::API; use Win32::OLE; my $autoIt = Win32::OLE->new("AutoItX3.Control"); my $app_title = "Test App"; my $nc_path = "C:/Program Files/Test App/TestApp.exe"; my $win_title_match = $autoIt->Opt("WinTitleMatchMode", 1); my $hwnd = $autoIt->ControlGetHandle($nc_title, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]"); Now that I have got the HWND of the embedded IE in my test application, the next step is to get the COM object or rather IDispatch object using that HWND. In IE.au3, __IEControlGetObjFromHWND() does that job & as I was reading that code, it was making calls to DllCall(). Where is this method from? Is is part of the AutoItX? I couldn't find it in the AutoItX help file. Or is it from the Win32 API? Or even better, does any one know how to get IDispatch object from a HWND directly in Perl? I am guessing, probably Win32::API but I am not sure. Any ideas?
Aditya Posted November 2, 2009 Author Posted November 2, 2009 Here is how far I got and the code below is continued from the post above. my $reg_window = new Win32::API('user32', 'RegisterWindowMessage', 'P', 'I'); my $html_obj = $reg_window->Call('WM_HTML_GETOBJECT'); my $SMTO_ABORTIFHUNG = 0x0002; my $lresult = " " x 80; my $send_msg = new Win32::API('user32', 'SendMessageTimeout', 'NIIIIIP', 'N'); $send_msg->Call(hex($hwnd), $html_obj, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lresult); my $aInt = pack('IIII', 0x626FC520, 0xA41E, 0x11CF, [0xA7, 0x31, 0x0, 0xA0, 0xC9, 0x8, 0x26, 0x37]); my $obj = new Win32::API('oleacc', 'ObjectFromLresult', 'PPIP' , 'N'); my $idisp = 0; my $ret = $obj->Call($lresult, $aInt, 0, $idisp); print "ret: ", $ret, "\n", "ie: ", $idisp, "\n"; But $idsp is always 0. So something is wrong in my code. Any suggestions?
Authenticity Posted November 2, 2009 Posted November 2, 2009 Seems you're missing CoInitializeEx before you call ObjectFromLresult. Refer to trancexx's post here
Aditya Posted November 2, 2009 Author Posted November 2, 2009 Seems you're missing CoInitializeEx before you call ObjectFromLresult. Refer to trancexx's post hereThanks for pointing it out, but adding that didn't help. Also the solution in the link you provided uses SendMessage, which works only with Vista & higher. I am trying to make this work in XP.
Authenticity Posted November 2, 2009 Posted November 2, 2009 (edited) The value you set to $aInt should be so or it should be IID_IHTMLDocument?IID_IHTMLDocument is 626FC520-A41E-11CF-A731-00A0C9082637.Edit Anyway, you said you need to use SendMessageTimeout instead right? This is from the same topic I've linked to, just a minor fix to someone's wrong DllCall() arguments types:expandcollapse popup#include <WinAPI.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') 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 EndFuncIt seems you're using to correct object GUID but I know nothing about perl so it may be something with how you set the variables. Edited November 2, 2009 by Authenticity
Aditya Posted November 2, 2009 Author Posted November 2, 2009 (edited) The value you set to $aInt should be so or it should be IID_IHTMLDocument? IID_IHTMLDocument is 626FC520-A41E-11CF-A731-00A0C9082637. Yup, my packing was wrong - here is the updated one: my $aInt = pack('LSSC8',0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37); Another change I made was to unpack the $lresult (I dunno why it was accepting the unpacked lresult) that I get back from SendMessageTimeout. So my updated code looks like this: my $co_init = new Win32::API('ole32', 'CoInitialize', 'P', 'I'); $co_init->Call(0); my $reg_window = new Win32::API('user32', 'RegisterWindowMessage', 'P', 'I'); my $html_obj = $reg_window->Call('WM_HTML_GETOBJECT'); my $SMTO_ABORTIFHUNG = 0x0002; my $lresult = " " x 80; my $send_msg = new Win32::API('user32', 'SendMessageTimeout', 'NIIIIIP', 'N'); $send_msg->Call(hex($hwnd), $html_obj, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lresult); $lresult = unpack('L', $lresult); my $aInt = pack('LSSC8',0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37); my $obj = new Win32::API('oleacc', 'ObjectFromLresult', 'PPIP' , 'N'); my $idisp = " " x 8; my $obj = new Win32::API('oleacc', 'ObjectFromLresult', 'NPIP' , 'N'); my $ret = $obj->Call($lresult, $aInt, 0, $idisp); print "Error: ", $autoIt->error(), "\n"; print "ret: ", $ret, "\n", "ie: ", $idisp, "\n", "idisp: ", unpack('L', $idisp), "\n"; Now, I do get some value set for $idisp and is a scalar reference. I guess this is the COM object I am looking for, but I am unable to call methods like Script.Document etc on it directly. So I guess I have to dig a little more. Edited November 2, 2009 by Aditya
Authenticity Posted November 3, 2009 Posted November 3, 2009 Can you show the way you're using the object?
Aditya Posted November 3, 2009 Author Posted November 3, 2009 (edited) Can you show the way you're using the object?$idisp->Script();But, Perl complains that it cannot locate the method - most probably because it is not an object reference. Edited November 3, 2009 by Aditya
Aditya Posted November 3, 2009 Author Posted November 3, 2009 Looking at it from another angle, can't I just convert the IE.au3 to a dll & call the methods directly from Perl (or any other language for that matter)? Will that work?
Aditya Posted November 3, 2009 Author Posted November 3, 2009 Looking at it from another angle, can't I just convert the IE.au3 to a dll & call the methods directly from Perl (or any other language for that matter)? Will that work?Never mind, I got the answer to that question in the forums.
Aditya Posted November 4, 2009 Author Posted November 4, 2009 (edited) I think I finally got the answer to my original question, when I posted it here - http://perlmonks.org/?node_id=804864. The function was returning a pointer and not a Perl object. So I have to create a Perl object from that pointer. I still have to do that part but it is the answer I was looking for. When I finish my code, I'll post it here for future reference. Thanks for all your help. Edited November 4, 2009 by Aditya
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