Project

General

Profile

Actions

Bug #2079

closed

win32ole's OLEGEN does not create all classes needed when a TLB has more than one class defined

Added by sardaukar (Bruno Antunes) over 14 years ago. Updated almost 13 years ago.

Status:
Closed
ruby -v:
1.9.1
[ruby-core:25511]

Description

=begin
Hello.

If this is not a Ruby issue, I apologize, but I thought it would be best to contact the people responsible for Win32OLE, so here goes.

I have this TLB, and when I run OLEGEN (\doc\ruby\ruby-1.9.1\sample\win32ole) I obtain a file that is either incomplete or I'm missing something. It only generates one class and 5 modules. If so, how can I run, for example, AcdEvent's Connect() method since there's no class to instantiate AcdEvent objects?

Please help if you can, with either a patch to OLEGEN or some other way to achieve this result.

I have attached to this issue the TLB file in question, the generated (by OLEGEN) source file and a screen shot of Reflector's output of the DLL contents after importing the TLB into a Visual Studio project.

Thank you!
=end


Files

Ccs.tlb (5.06 KB) Ccs.tlb The TLB file sardaukar (Bruno Antunes), 09/10/2009 11:06 PM
ccs19.rb (10 KB) ccs19.rb generated proxy class sardaukar (Bruno Antunes), 09/10/2009 11:06 PM
reflect.PNG (6.3 KB) reflect.PNG RedGate Reflector.net output sardaukar (Bruno Antunes), 09/10/2009 11:06 PM
Actions #1

Updated by suke (Masaki Suketa) over 14 years ago

  • Status changed from Open to Assigned
  • Assignee set to suke (Masaki Suketa)

=begin

=end

Actions #2

Updated by suke (Masaki Suketa) over 14 years ago

=begin
What is the result of the following code?
require 'win32ole'
tlib = WIN32OLE_TYPELIB.new("Ccs.tlb")
tlib.ole_classes.each do |k|
if k.ole_type == "Class" && k.visible?
if k.progid && k.guid
puts k.name
end
end
end

Win32OLE does not know how to instantiate the class
without progid and guid.
So, OLEGEN outputs the class only when progid and guid
are given.
=end

Actions #3

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
The output is indeed only "AcdAutomationServer". How can Visual Studio generate 3 classes, then? Is there a way around this?

Thank you for your help!
=end

Actions #4

Updated by suke (Masaki Suketa) over 14 years ago

=begin
I'm not sure but I think Visual Studio does not check progid and
guid (and perhaps visibility).

What is the result of the following?

require 'win32ole'
tlib = WIN32OLE_TYPELIB.new("Ccs.tlb")
tlib.ole_classes.each do |k|
if k.ole_type == "Class"
puts k.name
end
end

Win32OLE can not instantiate without progid and guid,
So, OLEGEN outputs the class only if progid and guid are given.
But Win32OLE could recognize which is the class.

=end

Actions #5

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
Here's the output of the new code you sent:


AcdAutomationServer
AcdEvent
AcdObject

(this would be what I would need)
=end

Actions #6

Updated by suke (Masaki Suketa) over 14 years ago

=begin
What is the result of the following?

require 'win32ole'
tlib = WIN32OLE_TYPELIB.new("Ccs.tlb")
tlib.ole_classes.each do |k|
if k.ole_type == "Class"
puts k.name
p k.progid
p k.guid
puts "---"
end
end

If k.progid and k.guid are given, then Win32OLE could instantiate the class.
But k.progid or k.guid is nil, then Win32OLE can't instantiate the class.

=end

Actions #7

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
Here's the output:

AcdAutomationServer
"Ccs.Application"
"{BAA135B0-F931-11D0-9C14-0060973155F0}"

AcdEvent
nil
"{BAA135B3-F931-11D0-9C14-0060973155F0}"

AcdObject
nil
"{3AF626A0-08D7-11D1-9C32-0060973155F0}"

I understand it can't work right now - but isn't there any way it could work?

Thanks again
=end

Actions #8

Updated by suke (Masaki Suketa) over 14 years ago

=begin
It may crash ruby, so TRY AT YOUR OWN RISK,

To instantiate AcdEvent:
WIN32OLE.new("{BAA135B3-F931-11D0-9C14-0060973155F0}")
To instantiate AcdObject:
WIN32OLE.new("{3AF626A0-08D7-11D1-9C32-0060973155F0}")

Anyway, I recommend you to ask the provider of Ccs.tlb
how to instantiate AcdEvent and AcdObject in VBScript.

If VBScript can instantiate AcdEvent and AcdObject,
then Win32OLE could instantiate AcdEvent and AcdObject as same way.

=end

Actions #9

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
I tried, here's the result:

test.rb:3:in initialize': failed to create WIN32OLE object from {BAA135B3-F931
-11D0-9C14-0060973155F0}' (WIN32OLERuntimeError)
HRESULT error code:0x80040154
Class not registered
from test.rb:3:in new' from test.rb:3:in '

Here's how I do it now in VB.NET:


Public Server As Object
Public EventObject As Object
Public AcdEventObject As Object
Public AcdEventCallback As New EventReceiver
Public NotifReceiver As New DataReceiver

Server = CreateObject("Ccs.Application")
Server.GetEventHandler(EventObject)
AcdEventObject = EventObject
AcdEventObject.Connect(AcdEventCallback)
AcdEventObject.SetEventMask(ACD_EVENT_ALL)

In VB.NET (and I'm assuming VBScript too) one can just refer to them as "Object" type.
=end

Actions #10

Updated by suke (Masaki Suketa) over 14 years ago

=begin
Unfortunately, VB.NET is not same VBScript.
VB.NET support early binding and VBScript does not support early binding,
only support late binding.
And Win32OLE support late binding only like as VBScript not VB.NET.

According to your VB.NET code, AcdEvent object is not instantiated directly, instantiated
by AcdAutomationServer.GetEventHandler.
(This is because the progid of AcdEvent is not given. You should not instantiate
AcdEvent object directly.)

What's the definition of GetEventHandler in OLEGEN's output?
=end

Actions #11

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
Here it is:


Unknown Type 10 GetEventHandler

Returns the event handler

VARIANT arg0 --- Handler [OUT]

def GetEventHandler(arg0)
ret = _invoke(3, [arg0], [VT_BYREF|VT_VARIANT])
@lastargs = WIN32OLE::ARGV
ret
end

(inside the IAcdAutomationServer module)


Unknown Type 10 GetEventHandler

Returns the event handler

VARIANT arg0 --- Handler [OUT]

def GetEventHandler(arg0)
ret = @dispatch._invoke(3, [arg0], [VT_BYREF|VT_VARIANT])
@lastargs = WIN32OLE::ARGV
ret
end

(inside the Ccs_Application class)
=end

Actions #12

Updated by suke (Masaki Suketa) over 14 years ago

=begin
What's the result of the following script?
If the following script works fine, then you could obtain AcdEvent Object by accessing
WIN32OLE::ARGV[0].
If it does not work, unfortunately Win32OLE can't instantiate AcdEvent object.

server = WIN32OLE.new("Ccs.Application")
server._invoke(3, [nil], [VT_BYREF|VT_VARIANT])
p WIN32OLE::ARGV

=end

Actions #13

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
Here's the output:


test.rb:4:in `': uninitialized constant VT_BYREF (NameError)

After changing it to:


require 'win32ole'
include WIN32OLE::VARIANT

server = WIN32OLE.new("Ccs.Application")
server._invoke(3, [nil], [VT_BYREF|VT_VARIANT])
p WIN32OLE::ARGV

the output is this:


test.rb:5:in _invoke': (in OLE method ': ) (WIN32OLERuntimeErro
r)
OLE error code:0 in

HRESULT error code:0x80020005
Type mismatch.
from test.rb:5:in `'

=end

Actions #14

Updated by suke (Masaki Suketa) over 14 years ago

=begin

After changing it to:
Sorry that I forget to write including WIN32OLE::VARIANT.

Unfortunately, I think Win32OLE in Ruby 1.8 can't instantiate AcdEvent object.
If you use Ruby 1.9, then try

include WIN32OLE::VARIANT
obj = WIN32OLE_VARIANT.new(nil, VT_VARIANT|VT_BYREF)
server = WIN32OLE.new("Ccs.Application")
server.GetEventHandler(obj)
p obj
p obj.value

If it does not work, then Win32OLE can't instantiate AcdEvent object.
=end

Actions #15

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
I've always been using Ruby 1.9 (since I filed the bug as a 1.9 issue).

The output of your last program is:


#<WIN32OLE_VARIANT:0xac0f94>
#WIN32OLE:0xac0800

Does this mean there's a chance it could work?

=end

Actions #16

Updated by suke (Masaki Suketa) over 14 years ago

=begin
Yes, I think so.
It seems to me that obj.value is the AcdEvent object.

...

server.GetEventHandler(obj)
acdEventObject = obj.value
acdEventObject.XXX
...

=end

Actions #17

Updated by sardaukar (Bruno Antunes) over 14 years ago

=begin
It works!!! :D


require 'win32ole'
include WIN32OLE::VARIANT

class EventReceiver
def initialize
end
end

obj = WIN32OLE_VARIANT.new(nil, VT_VARIANT|VT_BYREF)
server = WIN32OLE.new("Ccs.Application")
server.GetEventHandler(obj)

AcdEventCallBack = EventReceiver.new

acdEventObject = obj.value
acdEventObject.Connect(AcdEventCallBack)


Thanks for all your help!
=end

Actions #18

Updated by suke (Masaki Suketa) over 14 years ago

  • Status changed from Assigned to Closed

=begin
Thank you for your reporting.
I closed this issue.
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0