Win32OLE: Output parameters, Dispatch IDs

Discussion in 'Ruby' started by Dave Burt, Dec 7, 2005.

  1. Dave Burt

    Dave Burt Guest

    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
     
    Dave Burt, Dec 7, 2005
    #1
    1. Advertising

  2. Dave Burt

    x1 Guest

    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?

    On 12/7/05, Dave Burt <> wrote:
    > Hi,
    >
    > x1 recently asked about an issue with a WMI script that had an output par=

    ameter.
    > I guess you can get a result from an output parameter via WIN32OLE#_invok=

    e (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 =3D WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_Process")
    > # Try to get the method
    > wmi_svc.ole_method("Create") #=3D> WIN32OLERuntimeError: Not found Creat=

    e
    > # Invoke the method
    > wmi_svc.invoke("Create", "notepad", nil, nil, nil) #=3D> (Creates notepa=

    d.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
    >
    >
    >
     
    x1, Dec 8, 2005
    #2
    1. Advertising

  3. Dave Burt

    Dave Burt Guest

    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/ruby/ruby-talk/151854?151368-152549
    >
    > It should easy to modify it to just show the roots.


    In the same thread, Stephen Kellett 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/feature.html

    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
     
    Dave Burt, Dec 8, 2005
    #3
  4. Dave Burt

    x1 Guest

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

    --not sure how accurate this would be once 2 or more instances of
    "notepad" are running simultaneously.

    On 12/8/05, Dave Burt <> wrote:
    > 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 G=

    C
    > 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/ruby/ruby-talk/151854?15=

    1368-152549
    > >
    > > It should easy to modify it to just show the roots.

    >
    > In the same thread, Stephen Kellett posted a link to a product called Rub=

    y
    > Memory Validator, which lists as a feature "References view. Display the
    > object reference graph for the application," and the screenshot looks lik=

    e
    > it would deal well with this issue.
    > http://www.softwareverify.com/rubyMemoryValidator/feature.html
    >
    > 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 t=

    o
    > get the array:
    > pid =3D nil
    > ObjectSpace.each_object(Array) do |arr|
    > pid =3D arr[3] if arr.size =3D=3D 4 && arr[0, 3] =3D=3D ["notepad", nil=

    , nil]
    > end
    >
    > There you go - recover it from the object pool without knowing where the
    > references to it are/were.
    >
    > Cheers,
    > Dave
    >
    >
    >
    >
     
    x1, Dec 9, 2005
    #4
  5. Dave Burt

    Guest

    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
     
    , Dec 9, 2005
    #5
  6. Dave Burt

    x1 Guest

    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 =3D `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.

    On 12/9/05, <> wrote:
    > x1 complained:
    > > --not sure how accurate this would be once 2 or more instances of
    > > "notepad" are running simultaneously.

    >
    > pids =3D []
    > ObjectSpace.each_object(Array) do |arr|
    > pid << arr[3] if arr.size =3D=3D 4 && arr[0, 3] =3D=3D ["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 #=3D> pid from the Win32-Utils library, or even to use
    > Win32API or DL to call CreateProcess() directly.
    >
    > Cheers,
    > Dave
    >
    >
    >
     
    x1, Dec 9, 2005
    #6
  7. Dave Burt

    Dave Burt Guest

    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
     
    Dave Burt, Dec 9, 2005
    #7
  8. Hello,

    In message "Re: Win32OLE: Output parameters, Dispatch IDs"
    on 05/12/09, "Dave Burt" <> 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 Suketa
     
    Masaki Suketa, Dec 9, 2005
    #8
  9. Dave Burt

    Dave Burt Guest

    Hi,

    Masaki Suketa 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/ruby-talk/154365

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

    Cheers,
    Dave
     
    Dave Burt, Dec 9, 2005
    #9
  10. Dave Burt

    x1 Guest

    On 12/9/05, Dave Burt <> 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 thi=

    ng
    > 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 Burt <> 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 Suketa!
    >
    > Cheers,
    > Dave


    Agreed! Masaki, thanks so much for your time and concern.
     
    x1, Dec 10, 2005
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    730
    Beat Bolli
    Jun 21, 2005
  2. Masaki Suketa
    Replies:
    4
    Views:
    417
    Dave Burt
    Mar 27, 2006
  3. Replies:
    0
    Views:
    107
  4. Jan Svitok
    Replies:
    3
    Views:
    212
    Pit Capitain
    Jan 4, 2007
  5. zxem
    Replies:
    1
    Views:
    266
Loading...

Share This Page