Forum: Ruby How to completely terminate a WIN32OLE Excel object?

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.
59cdea7d8f8b9f4fbfa57304bb952c17?d=identicon&s=25 Sven Suska (Guest)
on 2007-05-26 11:39
(Received via mailing list)
Hello,

I can't get rid of Excel, if I have ever called it,
even with such a simple script:

---------- code starts --------------
require 'win32ole'

def puts_win32ole_objects
  res = []
  ObjectSpace.each_object do |o|
    res << o if o.is_a? WIN32OLE
  end
  puts res.inspect
end

puts_win32ole_objects  # --> empty
xl = WIN32OLE.new('Excel.Application')
puts_win32ole_objects  # --> one object
xl.Quit
xl = nil
GC.start  # anything else I could do???
puts_win32ole_objects  # --> the object is still there
sleep 5
---------------------------------------------
And also the Excel process remains running in Windows.

Btw, even after the xl.Quit, the object remains fully functional,
so I could call o.Visible, o.Workbooks.Open(...) etc., it o were
the object (retrieved from ObjectSpace).

When the Ruby process is terminated (after sleep), the
Excel process will also terminate.

So, what's the proper way to handle this?

I've found the WIN32OLE.ole_free method, but they say
that it is for debugging only.


Thanks for your help

Sven
59cdea7d8f8b9f4fbfa57304bb952c17?d=identicon&s=25 Sven Suska (Guest)
on 2007-05-26 11:42
(Received via mailing list)
Sven Suska schrieb:

> I can't get rid of Excel, if I have ever called it,

And I forgot:
This happens both with Ruby 1.8.6 and 1.8.5.

Sven
B19b02a49b433c9e2e6e6c43785d2bfb?d=identicon&s=25 James Tucker (Guest)
on 2007-05-27 09:38
(Received via mailing list)
I can't replicate this:

>> require 'win32ole'
=> true
>>
?>   def puts_win32ole_objects
>>    res = []
>>    ObjectSpace.each_object do |o|
?>          res << o if o.is_a? WIN32OLE
>>      end
>>    puts res.inspect
>>   end
=> nil
>>
?>   puts_win32ole_objects  # --> empty
[]
=> nil
>> xl = WIN32OLE.new('Excel.Application')
=> #<WIN32OLE:0x34e20fc>
>> xl.Visible
=> false
>> puts_win32ole_objects  # --> one object
[#<WIN32OLE:0x34e20fc>]
=> nil
>> puts `tasklist | find /I "excel.exe"`
EXCEL.EXE                    508 Console                 0     10,132 K
=> nil
>> xl.Quit
=> nil
>> xl = nil
=> nil
>> GC.start  # anything else I could do???
=> nil
>> puts_win32ole_objects  # --> the object is still there
[]
=> nil
>> puts `tasklist | find /I "excel.exe"`
=> nil
59cdea7d8f8b9f4fbfa57304bb952c17?d=identicon&s=25 Sven Suska (Guest)
on 2007-05-27 12:54
(Received via mailing list)
Hello James,

James Tucker schrieb:

> I can't replicate this:
>
>>> require 'win32ole'
>>
> [... skipping irb session ...]


This is truely strange!

Thanks for pointing this out!

When I tried this with IRB on my machine,
I got the same result:
Excel termination worked normally.

So there must be some difference
when the is executed as a Ruby file vs. via IRB.


So far, I have no idea what it could be.
I have set both RUBYOPT and RUBLIB to empty strings,
I've run the file via SciTe and on the console (ruby filename.rb)
-- the Excel object persists under all those conditions.
It's only within IRB that it is cleaned up properly.

Both my Ruby186 and 185 installations were done with
the one-click installer. (if that is of any significance)


I would appreciate any further help on this issue.

Thank you
Sven
B19b02a49b433c9e2e6e6c43785d2bfb?d=identicon&s=25 James Tucker (Guest)
on 2007-05-27 16:53
(Received via mailing list)
Sven Suska wrote:
>
> This is truely strange!
>
> Thanks for pointing this out!
>
> When I tried this with IRB on my machine,
> I got the same result:
> Excel termination worked normally.
>
> So there must be some difference
> when the is executed as a Ruby file vs. via IRB.

Interesting indeed!

I can replicate from a .rb file.

In fact, loading the .rb in irb also works in the correct manner, on the
contrary, if I load the .rb in my hacked version of IRB, it does not.
This seems almost like it is hardcoded to work for irb, or it is
something to do with the way in which handles are being processed.

I have also noticed a similar behavior with shell execution.

A GC.start will clear used file handles from `` and system() calls in
IRB, and if documentation I have read elsewhere is correct, this is not
the case for 'normal execution'. Time to plough through IRBs source
tree, and start tracing.
E97181961afa48102e3a28daab69b904?d=identicon&s=25 Masaki Suketa (Guest)
on 2007-05-28 13:19
(Received via mailing list)
Hello,

In message "How to completely terminate a WIN32OLE Excel object?"
    on 07/05/26, Sven Suska <sven715rt@suska.org> writes:

> When the Ruby process is terminated (after sleep), the
> Excel process will also terminate.
>
> So, what's the proper way to handle this?
>
> I've found the WIN32OLE.ole_free method, but they say
> that it is for debugging only.

I am not sure, but it seems to me because of GC behavior.
I tested your script using Foo class instead of WIN32OLE.
And I've got same result as WIN32OLE.

--- code starts ---
class Foo
  def initialize(arg)
    @arg = arg
  end
  def Quit
  end
end

def puts_win32ole_objects
  res = []
  ObjectSpace.each_object do |o|
    res << o if o.is_a? Foo
  end
  puts res.inspect
end

puts_win32ole_objects  # --> empty
xl = Foo.new('Excel.Application')
puts_win32ole_objects  # --> one object
xl.Quit
xl = nil
GC.start  # anything else I could do???
puts_win32ole_objects  # --> the object is still there
sleep 5
puts_win32ole_objects  # --> the object is still there
--- code end ---

The Excel process is terminated when the WIN32OLE object is GCed.
But in this case, the WIN32OLE object is not GCed, so  the Excel
process is not terminated.

I recommend that you do not use WIN32OLE#ole_free(See following
REMARK!).
But if you want to terminate the process before the WIN32OLE object
GCed,
you can use WIN32OLE#ole_free.

REMARK!
  WIN32OLE#ole_free terminates the Excel process but
  the WIN32OLE object is not GCed.
  You should not access the WIN32OLE object after WIN32OLE#ole_free
  called.

  Regards
  Masaki Suketa
59cdea7d8f8b9f4fbfa57304bb952c17?d=identicon&s=25 Sven Suska (Guest)
on 2007-05-28 18:57
(Received via mailing list)
Masaki Suketa schrieb:

>I am not sure, but it seems to me because of GC behavior.
>I tested your script using Foo class instead of WIN32OLE.
>And I've got same result as WIN32OLE.
>
>
I cannot confirm that.
The last two outputs give the empty list on my system.
Independent of the Ruby version (1.8.6 or 1.8.5).

>  res = []
>xl = nil
>GC.start  # anything else I could do???
>puts_win32ole_objects  # --> the object is still there
>sleep 5
>puts_win32ole_objects  # --> the object is still there
>--- code end ---
>
>

>The Excel process is terminated when the WIN32OLE object is GCed.
>But in this case, the WIN32OLE object is not GCed, so  the Excel
>process is not terminated.
>
>
I see: it is all a matter of garbage collection.

>But if you want to terminate the process before the WIN32OLE object GCed,
>you can use WIN32OLE#ole_free.
>
>
Thanks for telling me -- this worked indeed, contrary to
WIN32OLE.ole_free.
It would be a dirty solution.

However, The point you made about GC, has inspired me towards further
experiments.
First, I created a second WIN32OLE.new('Excel Application'), just to see
if the first object might get 'recycled'.
What I found was, that two objects existed after the second object
creation,
but after the three terminating statements (quit -- nil -- GC),
only the second object remained. (Lazy recycling, ... :-) )

Encouraged by this surprising result, I tried other things, and then
this:
xl = Foo.new('Excel.Application')
puts_win32ole_objects
xl = nil
GC.start

Just not calling xl.Quit anymore, and -- the object is gone!
Simplest of all!

This looks like an easy solution, but no no, too early to jump for joy:
I encountered this behaviour for _any_ method I called on the xl object.
OK, so, the easy destruction only works for "virgin" objects.

Thus, so far, we have not yet found a gentle
way to finish a WIN32OLE/Excel object.
For the time being, I think I'll resort to
(not-so-gentle) WIN32OLE#ole_free.


Regards,
Sven
This topic is locked and can not be replied to.