Forums | Admin

Discussion Forums: open-discussion

Start New Thread Start New Thread

 

By: basu ks
RE: using win32api to get com object embedded [ reply ]  
2009-08-12 06:09
Hi Park,

It works fine.This is what i was looking for.

Thanks a lot for your time and quick support :)


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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-06-02 13:04
That's odd. In my test, it works fine.

I guess you tried to get the handle when the embedded IE is not ready or in a busy state.


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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-06-02 09:51
It seems the loaded win32ole.so is the original version not modified version.

Try require 'watir/win32ole/win32ole'
instead of require 'watir/win32ole'

And check the file size of win32ole.so, which should be 65622 bytes.

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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-06-01 13:25
According to the CHANGES of Watir, I guess connect_unknown was supported since 1.5.2.

Be careful of require statement:
require 'watir/win32ole'
not
require 'win32ole'

I tested it with watir 1.6.2


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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-05-30 10:05
Because the return value of get_control_from_hwnd is not an Watir object, you cannot call ie.title directly.

Here is a workaround for title:

ie = get_control_from_hwnd(handle)
ie.navigate('http://www.google.com')
sleep 1
ie = get_control_from_hwnd(handle)
puts ie.document.url
puts ie.document.title



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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-05-19 00:54
The first pure ruby version of win32ole is done.

It requires win32-api 1.4.1(unoffical version) to support event handling.

The win32ole.rb and api.so are avaiable at
http://121.78.227.9/win32-ole


By: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-05-15 01:03
The pure ruby version is almost done except some event handling.

The latest version is available at
http://121.78.227.9/win32-ole/win32ole.rb

The previous code can be written with win32ole.rb

require 'win32ole.rb'
obj = WIN32OLE.get_control_from_hwnd(handle)
ie = obj.Script.Document.parentWindow
ie.Navigate('http://www.google.com')



By: matt wolfe
RE: using win32api to get com object embedded [ reply ]  
2009-05-14 21:15
Hey Park, how is the pure ruby version coming?
No hurry just curious what the current status is.
Again, thanks for all your hard work.

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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-05-11 00:57
You have two choices.

One is to use Ruby 1.9.1 which has a method to attach handle to OLE object.

Two is to wait the pure ruby win32-ole.
The draft pure ruby version will come out in this week with my struggle.

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: Park Heesob
RE: using win32api to get com object embedded [ reply ]  
2009-05-07 04:47
The pure ruby version of Win32OLE is a complete replacement of Win32OLE extension module written in C.

Refer to the feature request:
http://rubyforge.org/tracker/index.php?func=detail&aid=25792&group_id=85&atid=414

It will soon come out, hopefully in this month.


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?

   Next Messages