Win32OLE trouble (custom ocx)

B

Barry Walker

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 <Unknown>
<No Description>
HRESULT error code:0x8000ffff
Catastrophic failure from test.rb:6

Can anyone point me toward the problem?

Thanks
 
J

Jeff

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 <Unknown>
<No Description>
HRESULT error code:0x8000ffff
Catastrophic failure from test.rb:6

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
forum.softiesonrails.com
 
B

Barry Walker

Jeff said:
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?
 
M

Masaki Suketa

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

In message "Re: Win32OLE trouble (custom ocx)"
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 Suketa
 
B

Barry Walker

Masaki said:
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 <Unknown>
<No Description>
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 <Unknown>
<No Description>
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.
 
M

Masaki Suketa

Hello,

In message "Re: Win32OLE trouble (custom ocx)"
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 <Unknown>
<No Description>
HRESULT error code:0x8000ffff
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

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 Suketa
 
B

Barry Walker

Masaki said:
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.

<HTML><HEAD><TITLE>OCX test</TITLE>
<SCRIPT LANGUAGE="VBScript">
Sub window_onLoad()
document.frmEx.out1.value=QPTnt1.Version
End Sub
</SCRIPT>
</HEAD><BODY>

<OBJECT ID="QPTnt1" WIDTH=16 HEIGHT=16
CLASSID="CLSID:884BD6BB-E4BA-4EEA-A632-D7A92541602F">
<PARAM NAME="_Version" VALUE="65536">
<PARAM NAME="_ExtentX" VALUE="423">
<PARAM NAME="_ExtentY" VALUE="423">
<PARAM NAME="_StockProps" VALUE="0">
</OBJECT>

<FORM NAME="frmEx">
<INPUT TYPE=Text SIZE=10 NAME="out1">
</FORM>
</BODY></HTML>

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
 
J

Jeff

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.

<HTML><HEAD><TITLE>OCX test</TITLE>
<SCRIPT LANGUAGE="VBScript">
Sub window_onLoad()
document.frmEx.out1.value=QPTnt1.Version
End Sub
</SCRIPT>
</HEAD><BODY>

<OBJECT ID="QPTnt1" WIDTH=16 HEIGHT=16
CLASSID="CLSID:884BD6BB-E4BA-4EEA-A632-D7A92541602F">
<PARAM NAME="_Version" VALUE="65536">
<PARAM NAME="_ExtentX" VALUE="423">
<PARAM NAME="_ExtentY" VALUE="423">
<PARAM NAME="_StockProps" VALUE="0">
</OBJECT>

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
softiesonrails.com
 
B

Barry Walker

Jeff Cohen 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?
 
B

Barry Walker

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
 
M

Masaki Suketa

Hello, sorry for being too late to reply.

In message "Re: Win32OLE trouble (custom ocx)"
http://seclib.blogspot.com/2005_06_01_archive.html


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 Suketa
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top