Win32ole

Hi,

Is there any way to know the oleserver a WIN32OLE object is using? For
example:

conn = WIN32OLE.new(“ADODB.Connection”)
p conn.class

which will ouput WIN32OLE, but not ADODB.Connection. How can I tell in
program what oleserver an ole object is using?

Tks
Shannon

“Shannon Fang” xrfang@hotmail.com wrote in message
news:20021201171642.EBC5.XRFANG@hotmail.com

Hi,

Is there any way to know the oleserver a WIN32OLE object is using? For
example:

conn = WIN32OLE.new(“ADODB.Connection”)
p conn.class

which will ouput WIN32OLE, but not ADODB.Connection. How can I tell in
program what oleserver an ole object is using?

Generally you can’t do this easily - not unless the COM object supports an
interface to provide that information.

Typically a COM object is implemented in-proc as a dll. It basically works
exactly like Ruby extensions except different conventions for calling and
discovering methods.
It’s a bit like asking what ruby extension does my Ruby object live in.

Below I’ll show how you find that dll - it’s indirectly also what WINOLE32
does to locate the component.
You ask what “program” it calls. COM generally doesn’t call programs -
rather programs call COM components. Thus you won’t find any references to
Access2000, Excell or whatever. Basically Excell is a large pile of COM
components with a tiny GUI layer on top.

To find out more about the objects you have to inspect the registry. It’s
fairly messy in general, but I’ll give you two lookups that will handle most
cases:

My qualified guess is that WINOLE32 calls CoCreateInstance behind the
covers. CoCreateInstance depends on COM classes being registered in a
certain way. The following is how most components are registered:

The registry lookup is in pseudo notation - you’d have to figure out exactly
how to operate the registry from Ruby using som WIN32 API functions or
similar, I’d rather not be bothered with the details but here is the general
approach (you can do this manually using regedit).

First you look up

myclsid = \HKEY_CLASSES_ROOT\ADODB.Connect\CLSID

where you replace “ADODB.Connection” with whatever you want to know about.
This is called the version independent ProgID. You may also specify a
version, for example “ADODB.Connection.1” - this won’t change when you
installa new MDAC components, but the first one will be updated to the
latest version.

Anyway, know you have a unique CLSID (128 bit identifier in a common string
format) which maps directly to the physical location of the component. In
order to get this info you execute a second lookup:

\HKEY_CLASSES_ROOT\CLSID<myclsid>

This yields a directory, where one key is probably “InprocServer32”.
The default value in this subkey is the directory to the inproc server, i.e.
the dll.

Mikkel

Is there any way to know the oleserver a WIN32OLE object is using? For
example:

conn = WIN32OLE.new(“ADODB.Connection”)
p conn.class

which will ouput WIN32OLE, but not ADODB.Connection. How can I tell in
program what oleserver an ole object is using?

If you know a COM call which will return this info (maybe class does), but
there’s a Ruby call by the same name getting in the way, you can do:

conn.invoke(“class”)

which forces the call through to the COM object, bypassing any
coincidentally named native Ruby methods.

Chris

It is not perfect, but how about WIN32OLE#ole_obj_help ?

p conn.ole_obj_help.name

Regards,
Masaki Suketa

···

In message “WIN32OLE” on 02/12/02, Shannon Fang xrfang@hotmail.com writes:

Is there any way to know the oleserver a WIN32OLE object is using? For
example:

conn = WIN32OLE.new(“ADODB.Connection”)
p conn.class

which will ouput WIN32OLE, but not ADODB.Connection. How can I tell in
program what oleserver an ole object is using?

Hi,

Thanks for the info. However, what I want is not to find out the com dll,
but what did the win32ole obj used. for example,

conn=WIN32OLE.new(“ADODB.Connection”)
xl=WIN32OLE.new(“Excel.Application”)

conn.class==xl.class >> True

In RUBY program, how can I know if a win32ole object is an instance of
adodb or excel?

Shannon

···

On Mon, 2 Dec 2002 05:24:51 +0900 “MikkelFJ” mikkelfj-anti-spam@bigfoot.com wrote:

“Shannon Fang” xrfang@hotmail.com wrote in message
news:20021201171642.EBC5.XRFANG@hotmail.com

Hi,

Is there any way to know the oleserver a WIN32OLE object is using? For
example:

conn = WIN32OLE.new(“ADODB.Connection”)
p conn.class

which will ouput WIN32OLE, but not ADODB.Connection. How can I tell in
program what oleserver an ole object is using?

Generally you can’t do this easily - not unless the COM object supports an
interface to provide that information.

Typically a COM object is implemented in-proc as a dll. It basically works
exactly like Ruby extensions except different conventions for calling and
discovering methods.
It’s a bit like asking what ruby extension does my Ruby object live in.

Below I’ll show how you find that dll - it’s indirectly also what WINOLE32
does to locate the component.
You ask what “program” it calls. COM generally doesn’t call programs -
rather programs call COM components. Thus you won’t find any references to
Access2000, Excell or whatever. Basically Excell is a large pile of COM
components with a tiny GUI layer on top.

To find out more about the objects you have to inspect the registry. It’s
fairly messy in general, but I’ll give you two lookups that will handle most
cases:

My qualified guess is that WINOLE32 calls CoCreateInstance behind the
covers. CoCreateInstance depends on COM classes being registered in a
certain way. The following is how most components are registered:

The registry lookup is in pseudo notation - you’d have to figure out exactly
how to operate the registry from Ruby using som WIN32 API functions or
similar, I’d rather not be bothered with the details but here is the general
approach (you can do this manually using regedit).

First you look up

myclsid = \HKEY_CLASSES_ROOT\ADODB.Connect\CLSID

where you replace “ADODB.Connection” with whatever you want to know about.
This is called the version independent ProgID. You may also specify a
version, for example “ADODB.Connection.1” - this won’t change when you
installa new MDAC components, but the first one will be updated to the
latest version.

Anyway, know you have a unique CLSID (128 bit identifier in a common string
format) which maps directly to the physical location of the component. In
order to get this info you execute a second lookup:

\HKEY_CLASSES_ROOT\CLSID<myclsid>

This yields a directory, where one key is probably “InprocServer32”.
The default value in this subkey is the directory to the inproc server, i.e.
the dll.

Mikkel

“Shannon Fang” xrfang@hotmail.com wrote in message
news:20021201234814.B9E0.XRFANG@hotmail.com

Hi,

Thanks for the info. However, what I want is not to find out the com dll,
but what did the win32ole obj used. for example,

conn=WIN32OLE.new(“ADODB.Connection”)
xl=WIN32OLE.new(“Excel.Application”)

conn.class==xl.class >> True

In RUBY program, how can I know if a win32ole object is an instance of
adodb or excel?

I don’t know the details of WIN32OLE, but it could cache the intial argument
to new.
You can easily subclass WIN32OLE to handle this in the case where WIN32OLE
creates the object. However, many objects are not created that way. You
create the top level document object, and the this object creates sheet,
table, cell objects etc. which are just returned to you as if they are
properties or similar. You have no easy way to identify what these returned
objects are.

You can do two things with a COM object: You can see if two objects are
physically identical (comparing IUnknow pointers). And you can ask what
interfaces the object supports (using Query interface).

In dynamic scripting languages like Ruby, it is difficult to work with
multiple interfaces because these are binary interfaces using vtable
function pointers. Instead the functionality of an object is typically
reflected into a single interface IDispatch which WIN32OLE (and other
scripting language COM bindings) understands. IDispatch is (essentially) a
way to execute methods by supplying a name as a string and arguments as an
array. This means that to Ruby all objects are the same type (IDispatch)
except each object may generate error on different method names.

Note that even though objects look the same to Ruby, any COM object,
receiving a reference to another COM object from Ruby, will be able pick the
interface of interest from that object. If such an object doesn’t get what
it wants, it’ll be upset and either crash, or more likely generate an error
that can be interpreted in Ruby. Therefore you can indirectly check for a
type by spamming a COM object with other objects and see if it gets upset
assuming you can find an appropriate method to do so with. For example,
there may be a method AddSpreadsheet, which will get upset if doesn’t
receive spreadsheet objects (of course it has the unfortunate sideeffect of
adding the object in case of success …).

Perhaps WIN32OLE supports providing info on what interfaces an object
supports, even if you can’t use the interfaces directly in Ruby, but I doubt
it. On the other hand, I’d expect WIN32OLE to be able to compare objects for
physical identity.

It is possible to write a COM object in C++ or VB 6.0 which can be operated
from Ruby and provide some of the information you require - this task can be
fairly easy of you write objects that recognizes specific hardcoded
interfaces. This is a cleaner variant of the spamming method described
above.

Mikkel

You can get GUID(UUID) from WIN32OLE_TYPE object.

require ‘win32ole’

conn = WIN32OLE.new(“ADODB.Connection”) #=> #WIN32OLE:0x2b04c78
conn_type = conn.ole_obj_help #=> #<WIN32OLE_TYPE:0x2b059e0>
conn_type.guid #=> “{00000550-0000-0010-8000-00AA006D2EA4}”
conn_type.helpstring #=> “”
conn_type.helpfile #=> “C:\WINNT\HELP\ado210.chm”
conn_type.helpcontext #=> 1231105

xl=WIN32OLE.new(“Excel.Application”)
xl_type = xl.ole_obj_help
xl_type.guid #=> “{000208D5-0000-0000-C000-000000000046}”
xl_type.helpstring #=> “”
xl_type.helpfile #=> “C:\MyProg\MSOffice\Office\VBAXL9.CHM”
xl_type.helpcontext #=> 131073

conn2 = WIN32OLE.new(“ADODB.Connection”) #=> #WIN32OLE:0x2a923e8

conn_type.guid == xl_type.guid #=> false
conn_type.guid == conn2.ole_obj_help.guid #=> true

Some inferface has a ‘helpstring’, which is more readable than guid. :slight_smile:

ie = WIN32OLE.new(‘InternetExplorer.Application’)
ie_type = ie.ole_obj_help
ie_type.guid #=> “{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}”
ie_type.helpstring #=> “Web Browser Interface for IE4.”
ie_type.helpfile #=> “”
ie_type.helpcontext #=> 0

···

On Sun, 01 Dec 2002 23:50:25 GMT Shannon Fang xrfang@hotmail.com wrote:

Thanks for the info. However, what I want is not to find out the com dll,
but what did the win32ole obj used. for example,

conn=WIN32OLE.new(“ADODB.Connection”)
xl=WIN32OLE.new(“Excel.Application”)

conn.class==xl.class >> True

In RUBY program, how can I know if a win32ole object is an instance of
adodb or excel?


Shusaku tsyk@yk.rim.or.jp