 |
Forums |
Admin Start New Thread
By: Park Heesob
RE: using win32api to get com object embedded [ reply ] 2009-08-11 10:15
|
Hi,
It is possible to get IWebBrowser2 like this:
require 'watir/win32ole'
require 'windows/com'
require 'windows/unicode'
require 'windows/error'
require 'windows/national'
require 'windows/window/message'
require 'windows/msvcrt/buffer'
include Windows::COM
include Windows::Unicode
include Windows::National
include Windows::Error
include Windows::Window::Message
include Windows::MSVCRT::Buffer
SMTO_ABORTIFHUNG = 0x0002
ObjectFromLresult = Win32::API.new('ObjectFromLresult', 'LPIP', 'L', 'oleacc')
IID_NULL = [0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00].pack('LSSC8')
def get_htmldocument2(hnd)
CoInitialize(0)
reg_msg = RegisterWindowMessage("WM_HTML_GETOBJECT")
iid =[0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37].pack('LSSC8')
iid2 =[0x332C4425,0x26CB,0x11D0,0xB4,0x83,0x00,0xC0,0x4F,0xD9,0x01,0x19].pack('LSSC8')
result = 0.chr*4
SendMessageTimeout(hnd.hex, reg_msg, 0, 0, SMTO_ABORTIFHUNG,1000, result)
result = result.unpack('L')[0]
pDisp = 0.chr * 4
r = ObjectFromLresult.call(result, iid2, 0, pDisp)
if r == 0
pDisp = pDisp.unpack('L').first
ucPtr = multi_to_wide("parentWindow")
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,28)
table = table.unpack('L*')
getIDsOfNames = Win32::API::Function.new(table[5],'PPPLLP','L')
dispID = 0.chr * 4
getIDsOfNames.call(pDisp,IID_NULL,[ucPtr].pack('P'),1,LOCALE_USER_DEFAULT,dispID)
dispID = dispID.unpack('L').first
dispParams = [0,0,0,0].pack('LLLL')
res = 0.chr * 16
invoke = Win32::API::Function.new(table[6],'PLPLLPPPP','L')
hr = invoke.call(pDisp,dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,DISPATCH_PROPERTYGET | DISPATCH_METHOD,dispParams, res, nil, nil)
if hr != S_OK
raise StandardError, "IDispatch::Invoke() failed with %08x" % hr
end
res = res.unpack('SSSSLL')
if res[0] == VT_DISPATCH
return res[4]
end
else
nil
end
end
def get_webbrowser2(hnd)
iid_IServiceProvider = [0x6d5140c1,0x7436,0x11ce,0x80,0x34,0x00,0xaa,0x00,0x60,0x09,0xfa].pack('LSSC8')
iid_IWebBrowserApp = [0x0002DF05,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46].pack('LSSC8')
iid_IWebBrowser2 = [0xD30C1661,0xCDAF,0x11D0,0x8A,0x3E,0x00,0xC0,0x4F,0xC9,0xE2,0x6E].pack('LSSC8')
pDisp = get_htmldocument2(hnd)
return nil if pDisp.nil?
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,12)
table = table.unpack('L*')
queryInterface = Win32::API::Function.new(table[0],'PPP','L')
dispID = 0.chr * 4
queryInterface.call(pDisp,iid_IServiceProvider,dispID)
pDisp = dispID.unpack('L').first
lpVtbl = 0.chr * 4
table = 0.chr * 28
memcpy(lpVtbl,pDisp,4)
memcpy(table,lpVtbl.unpack('L').first,16)
table = table.unpack('L*')
queryService = Win32::API::Function.new(table[3],'PPPP','L')
dispID = 0.chr * 4
queryService.call(pDisp,iid_IWebBrowserApp,iid_IWebBrowser2,dispID)
dispID = dispID.unpack('L').first
if dispID>0
WIN32OLE.connect_unknown(dispID)
else
nil
end
end
a = get_webbrowser2('002707AE')
a.Navigate('http://www.google.com')
-----------------------------------------
Regards,
Park Heesob
|
By: basu ks
RE: using win32api to get com object embedded [ reply ] 2009-08-05 09:14
|
Hi park,
I hope it is possible to get IWebBrowser2 (web browser control , i think watir uses this for automation of IE) object from the IE handle.
Ref:
http://www.forum.it-berater.org/index.php?topic=574.0
http://www.koders.com/csharp/fid6F978057C244AF9B86D70D0D02752A3E9096C893.aspx
I tried converting the 'Internet Explorer_server1' control handle to IHtmlDocument2, i lost some where, could you plz help me to get IWebBrowser2 object?
Thanks in advance
def get_htmldocument(hnd)
smto_abortif_hung = 0x0002
object_from_lresult = Win32::API.new('ObjectFromLresult', 'LPIP', 'L', 'oleacc')
CoInitialize(0)
reg_msg = RegisterWindowMessage("WM_HTML_GETOBJECT")
idisp = 0.chr * 4
result = 0.chr*4
SendMessageTimeout(hnd.hex, reg_msg, 0, 0, smto_abortif_hung,1000, result)
result = result.unpack('L')[0]
r = object_from_lresult.call(result, UUID.new("{332C4425-26CB-11D0-B483-00C04FD90119}"), 0, inet)
inet = inet.unpack('L').first
end
|
By: Park Heesob
RE: using win32api to get com object embedded [ reply ] 2009-06-09 14:05
|
I think It is impossible to return a Watir object from get_control_from_hwnd.
Watir wants COM object of IEFrame but get_control_from_hwnd returns COM object of Internet Explore_Server.
It lacks some properties like busy, readyState etc.
If you really want Watir Object, Redefining some methods like wait is needed. Try this:
module Watir
class IE
def wait
sleep 1
end
end
end
# Get winamp embedded ie
embedded_ie = get_control_from_hwnd(autoit.ControlGetHandle("TEST", "", "Internet Explorer_Server1"))
ie = Watir::IE.new(true)
ie.ie = embedded_ie
ie.goto('http://www.google.com')
Regards,
Park Heesob
|
By: Andre Pretorius
RE: using win32api to get com object embedded [ reply ] 2009-06-09 09:59
|
Hi Park,
Thank you for your reply and your suggestion, it works perfect :)
I am just curious if we will be able to return a Watir object from get_control_from_hwnd in the near future, to make is possible to use Watir methods and properties as normal?
Or is there some way to inherit from Watir? (being a novice programmer still, I am not sure if this is possible)
Thanks,
Andre
|
By: basu ks
RE: using win32api to get com object embedded [ reply ] 2009-06-02 11:07
|
Replaced win32ole.so in C:\ruby\lib\ruby\gems\1.8\gems\watir-1.5.6\watir\win32ole
with the latest one (i.e one which is 65KB), facing `method_missing': unknown property or method `parentwindow' (WIN32OLERuntimeError)
HRESULT error code:0x80020006
issue ?
|
By: basu ks
RE: using win32api to get com object embedded [ reply ] 2009-06-02 05:43
|
Hi Park,
I am not able to figure out the issue with this code; throwing exception undefined 'connect_unknown' method
require 'watir/win32ole'
require 'windows/com'
require 'windows/window/message'
include Windows::COM
include Windows::Window::Message
SMTO_ABORTIFHUNG = 0x0002
ObjectFromLresult = Win32::API.new('ObjectFromLresult', 'LPIP', 'L', 'oleacc')
def get_control_from_hwnd(hnd)
CoInitialize(0)
reg_msg = RegisterWindowMessage("WM_HTML_GETOBJECT")
iid =[0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37].pack('LSSC8')
result = 0.chr*4
SendMessageTimeout(hnd.hex, reg_msg, 0, 0, SMTO_ABORTIFHUNG,1000, result)
result = result.unpack('L')[0]
idisp = 0.chr * 4
r = ObjectFromLresult.call(result, iid, 0, idisp)
if r == 0
idisp = idisp.unpack('L').first
WIN32OLE.connect_unknown(idisp).Script.Document.parentwindow
else
nil
end
end
autoit = WIN32OLE.new('AutoItX3.Control')
# Get winamp embedded ie
embedded_ie = get_control_from_hwnd(autoit.ControlGetHandle("Main Window", "", "Internet Explorer_Server1"))
embedded_ie.navigate('http://www.google.com')
|
By: basu ks
RE: using win32api to get com object embedded [ reply ] 2009-06-01 11:58
|
Hi Park ,
I tried using your code, am getting the error as
`get_control_from_hwnd': undefined method `connect_unknown' for WIN32OLE:Class (NoMethodError)
I am using watir 1.5.6, for which version of the watir this code will work?
|
By: Andre Pretorius
RE: using win32api to get com object embedded [ reply ] 2009-05-29 10:01
|
Hi Park,
This is exactly what I have been looking for as well (you made my day) :) I also have an embedded IE window that I need to test using Watir and used your latest thread entry code which successfully connected to my embedded browser which then navigated to google.
I am also rather new to Watir and Ruby... and was wondering why I am getting the following error when executing the 'ie.title' method :
C:/.../watir_example.rb:40:in `method_missing': unknown property or method `title' (WIN32OLERuntimeError)
HRESULT error code:0x80020006
Unknown name.
Is it possible to use the existing Watir methods here? or am I missing something crucial..
|
By: Park Heesob
RE: using win32api to get com object embedded [ reply ] 2009-05-21 06:33
|
I noticed the watir has it's own win32ole.
Here is another version using watir's win32ole
require 'watir/win32ole'
require 'windows/com'
require 'windows/window/message'
include Windows::COM
include Windows::Window::Message
SMTO_ABORTIFHUNG = 0x0002
ObjectFromLresult = Win32::API.new('ObjectFromLresult', 'LPIP', 'L', 'oleacc')
def get_control_from_hwnd(hnd)
CoInitialize(0)
reg_msg = RegisterWindowMessage("WM_HTML_GETOBJECT")
iid =[0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37].pack('LSSC8')
result = 0.chr*4
SendMessageTimeout(hnd.hex, reg_msg, 0, 0, SMTO_ABORTIFHUNG,1000, result)
result = result.unpack('L')[0]
idisp = 0.chr * 4
r = ObjectFromLresult.call(result, iid, 0, idisp)
if r == 0
idisp = idisp.unpack('L').first
WIN32OLE.connect_unknown(idisp).Script.Document.parentwindow
else
nil
end
end
ie = get_control_from_hwnd('0039052C')
ie.navigate('http://www.google.com')
|
By: Daniel Berger
RE: using win32api to get com object embedded [ reply ] 2009-05-11 02:57
|
Wow, I certainly wasn't expecting you to have it completed that fast. That will be awesome. :)
I've created the Windows::COM::Variant module that adds the COM variant functions, and added the IDispatch::Invoke constants to the Windows::COM module. Both in CVS.
Dan
|
By: matt wolfe
RE: using win32api to get com object embedded [ reply ] 2009-05-10 06:11
|
hey Park, I misunderstood your previous post about this not being an ole object. Calling the navigate function isnt important, but having the object to which I can call navigate on is important. Thus, is there anyway to get the OLE object from this dispatch pointer, besides waiting for the pure ruby version of win32ole? I'm trying to attach this to watir and that is the only way of doing so. Trying to control IE by going through all of those win32 calls would be an absurd amount of work, I would surely rather use autoit IE.au3 or c# than that.
|
By: matt wolfe
RE: using win32api to get com object embedded [ reply ] 2009-05-07 02:03
|
Thanks Park for your help.
I have no problem doing it myself at all, i'm just not real familiar with win32/com/ole stuff, its all brand new to me as of about a week or two ago.
Thanks though I think i can figure out how to do those last few steps.
FYI I just put up a jira ticket for adding this into watir here:
http://jira.openqa.org/browse/WTR-312
By the way win is the pure ruby version of Win32OLE going to come out, and will it only be available for ruby 1.9? Also, what exactly do you mean by pure ruby version of win32OLE?
Thanks again for your help and hopefully I can get this working so I can begin writing tests for our application.
|
By: Park Heesob
RE: using win32api to get com object embedded [ reply ] 2009-05-07 01:19
|
The return value is not an OLE object but a Dispatch pointer.
If you need to call navigate with the dispatch pointer, following process required:
1. Get ID of "Navigate" method.
2. Prepare parameter of Navigate method.
3. Call Invoke with the ID and parameter.
4. Translate the return value if needed.
If you do not want to do it by yourself, you can wait until we release the upcoming pure Ruby version of Win32OLE.
|
By: matt wolfe
RE: using win32api to get com object embedded [ reply ] 2009-05-06 19:28
|
I tried this code and tested that it returns res[4] (after the line: if res[0] == VT_DISPATCH)
However, i cannot call navigate on the returned object. Ruby tells me that res[4] is a Fixnum object.. This isn't the control, i'm not sure what this is. Do i need to do something else to call ie functions on this object?
|
By: matt wolfe
RE: using win32api to get com object embedded [ reply ] 2009-05-06 16:01
|
Wow, that is amazing. I have no idea how you wrote this function, but i'll get to testing it as soon as possible. My attention has been diverted at work to writing some front end code but i'll be back to automation next week.
Thank you so much for your time. If this works good and is tested by multiple people we should see if your hard work can be encorporated into the core watir code, maybe a function called
attach_embedded which takes either a window name or a hwnd.. We can get the hwnd from a window title pretty easily.. thus, probably
attach_embedded(how,what)
so passing attach_embedded(:hwnd,39343)
or attach_embedded(:title, 'My App')
will work.
What does everyone else think?
|
|
 |