Win32OLE trouble (custom ocx)

I’m trying to make calls to an OCX we developed in house. The OCX is an
interface to a FireWire network. Currently we use this OCX mostly for
C# programs. It’s several years old and fairly stable.

I have been able to access this OCX from VBScript, so I think the OCX is
script ready.

I’ve tried the win32ole test scripts on Excel files and they work as
described, so I’m confident Ruby and win32ole are operational.

I can see the class, the methods, and the arguments when I run soleb.rb.

I ran olegen and it created a proper looking class with all the methods.

It seems the object is created properly when I call it (at least no
errors are reported).

When I call any of the methods using .invoke or ._invoke I get the same
error message. This error is also the same if the method requires
arguments or not.

test.rb:6:in ‘invoke’:method_name (or ‘_invoke’:_invoke)
(WIN32OLERuntimeError)
OLE error code:0 in

HRESULT error code:0x8000ffff
Catastrophic failure from test.rb:6

Can anyone point me toward the problem?

Thanks

On Feb 28, 6:28 pm, Barry W. [email protected] wrote:

Can anyone point me toward the problem?

I’m pretty sure that HRESULT indicates a null pointer error. My guess
is it’s expecting an argument that you’re not passing, or something
like that. What is on line 6 of your script?

Jeff

Hello, this may not be the answer your question…,

In message “Re: Win32OLE trouble (custom ocx)”
on 07/03/02, Barry W. [email protected] writes:

What is on line 6 of your script?

Line 6 is the method call on the object after the object is created.

I noticed one other thing when browsing the differences between the
class olegen created for my OCX and the class it created for excel.

Have you tried to access your OCX without using olegen?

If you have been able to access your OCX from VBScript,
at first, try to access your OCX without using olegen
and _invoke.

For example, if you can access the OCX in VBScript:

Set obj = CreateObject(“Your.OCX”)
obj.your_method(10)

then, you could access the OCX in Win32OLE like as the following.

require ‘win32ole’
obj = WIN32OLE.new(“Your.OCX”)
obj.your_method(10)

If this approach is fail, try to use olegen and _invoke like
as the following.

require ‘win32ole’
include WIN32OLE::VARIANT
obj = WIN32OLE.new(“Your.OCX”)

The second parameter is optional.

obj._invoke(1, [10, nil], [VT_I2, VT_VARIANT])

And, I need more detail information to advise more effectively.
Could you show me the test.rb and the result of the following script?
(Before running script, please change “Your.OCX” and “your_method”
to fit your OCX.)

require ‘win32ole’
obj = WIN32OLE.new(“Your.OCX”)
m = obj.ole_method_help(“your_method”)
p m.dispid
m.params.each do |param|
puts “-----”
p param.ole_type
p param.ole_type_detail
p param.optional?
end

Regards,
Masaki S.

Masaki S. wrote:

Hello, this may not be the answer your question…,

I’m just trying to make it work. Any method is fine.

require ‘win32ole’
qp = WIN32OLE.new(“QPTnt.ocx”)

gives the error
qptest.rb:2:in initialize': unknown OLE server:QPTnt.ocx’
(WIN32OLERuntimeError)
HRESULT error code:0x800401f3
Invalid class string from qptest.rb:2:in `new’
from qptest.rb:2

Soleb shows the PROGID of my QPTnt class is QPTNT.QPTntCtrl.1
So I try:

require ‘win32ole’
qp = WIN32OLE.new(“QPTNT.QPTntCtrl.1”)
s= qp.Version

gives the error
qptest.rb:3:in `method_missing’: Version (WIN32OLERuntimeError)
OLE error code:0 in

HRESULT error code:0x8000ffff
Catastrophic failure from qptest.rb:3

But Version is a method shown in soleb.

If this approach is fail, try to use olegen and _invoke like
as the following.

require ‘win32ole’
include WIN32OLE::VARIANT
obj = WIN32OLE.new(“Your.OCX”)

I tried,
require ‘win32ole’
include WIN32OLE::VARIANT
qp = WIN32OLE.new(“QPTnt.OCX”)
s= qp.Version

gives
ptest.rb:3:in initialize': unknown OLE server:QPTnt.OCX’
(WIN32OLERuntimeError)
HRESULT error code:0x800401f3
Invalid class string from qptest.rb:3:in `new’
from qptest.rb:3

and
require ‘win32ole’
include WIN32OLE::VARIANT
qp = WIN32OLE.new(“QPTNT.QPTntCtrl.1”)
s= qp.Version

gives
qptest.rb:4:in `method_missing’: Version (WIN32OLERuntimeError)
OLE error code:0 in

HRESULT error code:0x8000ffff
Catastrophic failure from qptest.rb:4

I tried another method, Activate2 with the same results.

When I run

require ‘win32ole’
obj = WIN32OLE.new(“QPTNT.QPTntCtrl.1”)
m = obj.ole_method_help(“Version”)
p m.dispid
m.params.each do |param|
puts “-----”
p param.ole_type
p param.ole_type_detail
p param.optional?
end

I only get one number on one line.

36

When I run it for the Activate2 (which requires one arguement) method I
get:

55

“I4”
[“I4”]
false

It was a year ago I ran the OCX with VBSript and I can’t find the code.
I just remember that it worked and that it was very cumbersome so I
abandon it. As I recall I invoked QPTnt.ocx not QPTNT.QPTntCtrl.1.

Thank you so much for your help.

Jeff C. wrote:

What is on line 6 of your script?

Line 6 is the method call on the object after the object is created.

I noticed one other thing when browsing the differences between the
class olegen created for my OCX and the class it created for excel.

There are no [IN,OUT,OPTION] tags in the comments of my class. Soleb
doesn’t show [IN,OUT,OPTION] tags either when I browse my OLE object.
Are these tags necessary for proper operation?

Any idea why my methods don’t show them?

Hello,

In message “Re: Win32OLE trouble (custom ocx)”
on 07/03/03, Barry W. [email protected] writes:

  Catastrophic failure  from qptest.rb:4

I tried another method, Activate2 with the same results.

Sorry, I’m not sure, but this might be Win32OLE’s limit.

I only get one number on one line.

36

Thank you.
I guess olegen worked fine, and created the expected script code.
Perphaps the olegen created the script code like as the following.
Is that right?

require ‘win32ole’
obj = WIN32OLE.new(“QPTNT.QPTntCtrl.1”)
include WIN32OLE::VARIANT
obj._invoke(36, [], []) # this invokes Version.

But unfortunately, I think you would get the same result
even if you try above script.

When I run it for the Activate2 (which requires one arguement) method I
get:

55

“I4”
[“I4”]
false

Perphaps, I guess olegen created as the following code.

obj._invoke(55, [arg], [VT_I4])

And [IN, OUT, OPTION] tags are not needed in this case.

It was a year ago I ran the OCX with VBSript and I can’t find the code.
I just remember that it worked and that it was very cumbersome so I
abandon it. As I recall I invoked QPTnt.ocx not QPTNT.QPTntCtrl.1.

BTW, Does the following VBScript work?
Set obj = CreateObject(“QPTnt.ocx”)
obj.Version
or
Set obj = CreateObject(“QPTNT.QPTntCtrl.1”)
obj.Version

If it would not work, Win32OLE script does not work.

Regards,
Masaki S.

Masaki S. wrote:

BTW, Does the following VBScript work?
Set obj = CreateObject(“QPTnt.ocx”)
obj.Version
or
Set obj = CreateObject(“QPTNT.QPTntCtrl.1”)
obj.Version

If it would not work, Win32OLE script does not work.

You’re leading me toward the problem. That VBScript code does not work.
It actually gives the same error statement that win32ole gives!

I went back and tried to re-create my VBScript code. I remembered I
used “ActiveX Control Pad” to test the VBScript method last year.

This is code (embeded in and html doc and mostly generated by ActiveX
control pad) that works with my ocx.

OCX test

It works and returns the version of the OCX as specified by the Version
method.

Is there an equivalent Ruby syntax that might work?

Does this provide a clue why my ocx won’t work with the win32ole?

Thanks

Any chance that the CLSID that works (884BD6BB-E4BA-4EEA-A632-
D7A92541602F) is not registered correctly? Maybe QPTNT.QPTntCtrl.1 is
not the right ProgID for that particular CLSID? I think you’ll have
to check the registry to be sure.

Jeff

Jeff C. wrote:
I think you’ll have

to check the registry to be sure.

I’m no registry expert, but I used RegEdit to search for QPTntCtrl

I found 6 entries.

HKEY_CLASSES_ROOT\CLSID{884BD6BB-E4BA-4EEA-A632-D7A92541602F}\ProgID
QPTNT.QPTntCtrl.1

HKEY_CLASSES_ROOT\QPTNT.QPTntCtrl.1 QPTntControl
HKEY_CLASSES_ROOT\QPTNT.QPTntCtrl.1\CLSID
{884BD6BB-E4BA-4EEA-A632-D7A92541602F}

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID{884BD6BB-E4BA-4EEA-A632-D7A92541602F}\ProgID
QPTNT.QPTntCtrl.1

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\QPTNT.QPTntCtrl.1 QPTntControl
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\QPTNT.QPTntCtrl.1\CLSID
{884BD6BB-E4BA-4EEA-A632-D7A92541602F}

Looks to me like the CLSID is lined up with the ProgID.

Are there other things I should look for?

Hello, sorry for being too late to reply.

In message “Re: Win32OLE trouble (custom ocx)”
on 07/03/08, Barry W. [email protected] writes:

X.Y.Z: June 2005

"First, a little background: ActiveX controls are normally persisted to/from
some type of permanent storage, and they do this by implementing one or more
IPersist* interfaces. Containers are supposed to call one of the IPersist
methods to initialize or load the control upon creation.

He was able to make a patch to our .ocx and it seems to work well now.

It also seems possible that this issue could be fixed inside Win32OLE.

Thank you for your information. I have
addedWIN32OLE#ole_activex_initialize
to ruby trunk. The method invokes InitNew method of IPersistMemory
interface. I have checked that the method works fine
with very small simple MFC ActiveX control which has
only AboutBox method.

Regards
Masaki S.

I just wanted to close this thread with a happy ending!

My partner, the .ocx developer, found this posting from someone with
similar trouble.

http://seclib.blogspot.com/2005_06_01_archive.html

"First, a little background: ActiveX controls are normally persisted to/from
some type of permanent storage, and they do this by implementing one or more
IPersist* interfaces. Containers are supposed to call one of the IPersist
methods to initialize or load the control upon creation.

He was able to make a patch to our .ocx and it seems to work well now.

It also seems possible that this issue could be fixed inside Win32OLE.

Thanks for the help