[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to completely terminate a WIN32OLE Excel object?

enduro

5/26/2007 9:39:00 AM

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



6 Answers

enduro

5/26/2007 9:42:00 AM

0

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

James Tucker

5/27/2007 7:38:00 AM

0

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




Sven Suska wrote:
> 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
>
>
>
>


enduro

5/27/2007 10:55:00 AM

0

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


>
>
>
>
> Sven Suska wrote:
>
>> 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
>>
>>
>>
>>
>
>
>


James Tucker

5/27/2007 2:53:00 PM

0

Sven Suska wrote:
> 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.

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.

> 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
>
>
>>
>>
>>
>>
>> Sven Suska wrote:
>>
>>> 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
>>>
>>>
>>>
>>>
>>
>>
>>
>
>
>


Masaki Suketa

5/28/2007 11:19:00 AM

0

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


enduro

5/28/2007 4:56:00 PM

0

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).

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