Forum: Ruby Win32OLE: Output parameters, Dispatch IDs

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
dave (Guest)
on 2005-12-07 17:05
(Received via mailing list)
Hi,

x1 recently asked about an issue with a WMI script that had an output
parameter.
I guess you can get a result from an output parameter via
WIN32OLE#_invoke (with
VT_BYREF?) if you have the Dispatch ID for the method. But for a few WMI
objects
I've seen recently, I haven't been able to get a WIN32OLE_METHOD
instance for a
lot of methods, even ones that I can invoke. For example:

# Get a Win32_Process WMI object
wmi_svc = WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_Process")
# Try to get the method
wmi_svc.ole_method("Create")  #=> WIN32OLERuntimeError: Not found Create
# Invoke the method
wmi_svc.invoke("Create", "notepad", nil, nil, nil)  #=> (Creates
notepad.exe
process)

That last parameter is an output parameter which should return the PID
of the
created process as a uint32.

Is there a way I can get info on a method like that, and how do I get
the result
of an output parameter?

Cheers,
Dave
Vrtwo L. (Guest)
on 2005-12-08 07:39
(Received via mailing list)
I have not been able to figure anything out yet myself.

Do you know off hand how one would be able to find any variable
names(if exist) that are pointing to a given object?

For instance when looking at ObjectSpace.cantremembermethodname(Array)
You get something like:
["notepad", nil, nil, 333]

How would one be able to determine the object id and / or any variable
names associated with it?
dave (Guest)
on 2005-12-08 08:44
(Received via mailing list)
x1 wrote:
> I have not been able to figure anything out yet myself.

I figured.

> Do you know off hand how one would be able to find any variable
> names(if exist) that are pointing to a given object?

Just last week, Joel VanderWerf wrote, in "Re: Memory Leaks: How to see
GC
Roots?":
> There's a ruby patch to show what objects are reachable from the roots
> (and the chain of references in each case):
>
> http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/rub...
>
> It should easy to modify it to just show the roots.

In the same thread, Stephen K. posted a link to a product called
Ruby
Memory Validator, which lists as a feature "References view. Display the
object reference graph for the application," and the screenshot looks
like
it would deal well with this issue.
http://www.softwareverify.com/rubyMemoryValidator/...

I have not actually operated either of these two possible solutions.

> For instance when looking at ObjectSpace.cantremembermethodname(Array)
> You get something like:
> ["notepad", nil, nil, 333]
>
> How would one be able to determine the object id and / or any variable
> names associated with it?

But, it just occurred to me, you could cheat and do something like this
to
get the array:
pid = nil
ObjectSpace.each_object(Array) do |arr|
  pid = arr[3] if arr.size == 4 && arr[0, 3] == ["notepad", nil, nil]
end

There you go - recover it from the object pool without knowing where the
references to it are/were.

Cheers,
Dave
Vrtwo L. (Guest)
on 2005-12-09 04:16
(Received via mailing list)
ObjectSpace.each_object(Array) do |arr|
  pid = arr[3] if arr.size == 4 && arr[0, 3] == ["notepad", nil, nil]
end

--not sure how accurate this would be once 2 or more instances of
"notepad" are running simultaneously.
dave.burt (Guest)
on 2005-12-09 07:19
(Received via mailing list)
x1 complained:
> --not sure how accurate this would be once 2 or more instances of
> "notepad" are running simultaneously.

pids = []
ObjectSpace.each_object(Array) do |arr|
  pid << arr[3] if arr.size == 4 && arr[0, 3] == ["notepad", nil, nil]
end

You can easily collect them all. If you get one list before the Create
call and one after, the difference is likely to be the PID you're
after.

Of course, in practical Ruby, it's going to be easier to use
Process.create #=> pid from the Win32-Utils library, or even to use
Win32API or DL to call CreateProcess() directly.

Cheers,
Dave
Vrtwo L. (Guest)
on 2005-12-09 08:16
(Received via mailing list)
I find it strange that the win32ole package cant handle out params.

Hunting in ObjectSpace with a semi-production script doesn't give me
the "warm and fuzzies".

Creating a basic .vbs file and calling it as such:
    pid = `cscript.exe exec.vbs`.split("\n")[3]
...works, but it's still a hack IMO.

Thanks again for the kind suggestions but since I'm still learning
ruby, knowing the precise problem or solution with this scenario would
be optimal.
dave (Guest)
on 2005-12-09 09:46
(Received via mailing list)
x1 wrote:
> I find it strange that the win32ole package cant handle out params.

That's the thing, though, it _does_ explicitly handle out params. The
only
way I know of using them, though, is via "_invoke", and you need a
dispid
(method handle) to call that.

> Hunting in ObjectSpace with a semi-production script doesn't give me
> the "warm and fuzzies".

Fair enough, if you're then doing something destructive with the PID.

> Creating a basic .vbs file and calling it as such:
>     pid = `cscript.exe exec.vbs`.split("\n")[3]
> ..works, but it's still a hack IMO.

You haven't tried win32-utils? I imagine if you're doing this kind of
thing
you'll find it very useful.

http://rubyforge.org/projects/win32utils

> Thanks again for the kind suggestions but since I'm still learning
> ruby, knowing the precise problem or solution with this scenario would
> be optimal.

You're welcome. I actually emailed the start of this thread directly to
the
Win32OLE maintainer in hope he can enlighten us - he has sometimes taken
a
bit of time to get around to responding, so let's be patient on that
front.

Cheers,
Dave
masaki.suketa (Guest)
on 2005-12-09 11:03
(Received via mailing list)
Hello,

In message "Re: Win32OLE: Output parameters, Dispatch IDs"
    on 05/12/09, "Dave B." <removed_email_address@domain.invalid> writes:

> You're welcome. I actually emailed the start of this thread directly to the
> Win32OLE maintainer in hope he can enlighten us - he has sometimes taken a
> bit of time to get around to responding, so let's be patient on that front.
Sorry for being too late to reply.

> # Get a Win32_Process WMI object
> wmi_svc = WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_Process")
> # Try to get the method
> wmi_svc.ole_method("Create")  #=> WIN32OLERuntimeError: Not found Create
> # Invoke the method
> wmi_svc.invoke("Create", "notepad", nil, nil, nil)  #=> (Creates notepad.exe process)
 (snip)
> Is there a way I can get info on a method like that, and how do I get the result
> of an output parameter?

You can get the result of an output parameter using WIN32OLE::ARGV.

wmi_svc = WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_Process")
wmi_svc.invoke("Create", "notepad", nil, nil, nil)
p WIN32OLE::ARGV # => ["notepad", -2147352572, -2147352572, 1704]

I am going to investigate why ole_method is failed.
Please wait for a while.

  Regards,
  Masaki S.
masaki.suketa (Guest)
on 2005-12-09 11:44
(Received via mailing list)
Hello,

In message "Re: Win32OLE: Output parameters, Dispatch IDs"
    on 05/12/09, Masaki S. <removed_email_address@domain.invalid> writes:

> You can get the result of an output parameter using WIN32OLE::ARGV.
>
> wmi_svc = WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_Process")
> wmi_svc.invoke("Create", "notepad", nil, nil, nil)
> p WIN32OLE::ARGV # => ["notepad", -2147352572, -2147352572, 1704]
>
> I am going to investigate why ole_method is failed.
> Please wait for a while.

WIN32OLE researches type library to get info on method.
But, it seems to me that the "Create" method is not entried in the
type library "Microsoft WMI Scripting V1.1 Library".
So, Win32OLE was failed to get info on "Create" method and
unfortunately, there is no way to get info on the "Create" method.

  Regards,
  Masaki S.
dave (Guest)
on 2005-12-09 17:29
(Received via mailing list)
Hi,

Masaki S. wrote:
> Sorry for being too late to reply.

No need to apologize! And you're not even late - the thread's still warm
after less than 2 days.

>> Is there a way I can get info on a method like that, and how do I get the
>> result
>> of an output parameter?
>
> You can get the result of an output parameter using WIN32OLE::ARGV.

Thanks. That makes it easy.

It's not documented in the RDoc; I don't think RDoc supports constants
in C
code yet.

> I am going to investigate why ole_method is failed.
> Please wait for a while.

I came across a similar problem a while back, using ADSI, I think. Like
Daniel's issue here:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

Thanks a lot for looking into this and for all the effort you've put
into
this library over the years - you're a champ, Masaki S.!

Cheers,
Dave
Vrtwo L. (Guest)
on 2005-12-10 07:35
(Received via mailing list)
On 12/9/05, Dave B. <removed_email_address@domain.invalid> wrote:
<trim>
> Fair enough, if you're then doing something destructive with the PID.

Indeed I am! "-9 destructive" to be exact :D

> You haven't tried win32-utils? I imagine if you're doing this kind of thing
> you'll find it very useful.

Actually, I've looked at it but have a few reasons not to use it:
1) requires compilation with VC

2) portability. With pid handling needed on multiple systems, I prefer
to let the "ruby one click installer" be the only required component
for a complete restoration(apart from the scripts themselves)

3) still learning ruby. What better way than to get down and dirty? :-)


On 12/9/05, Dave B. <removed_email_address@domain.invalid> wrote:
<trim>
> Thanks a lot for looking into this and for all the effort you've put into
> this library over the years - you're a champ, Masaki S.!
>
> Cheers,
> Dave

Agreed! Masaki, thanks so much for your time and concern.
This topic is locked and can not be replied to.