Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[MSH] How to dispose a COM object

350 views
Skip to first unread message

dontBotherMeWithSpam

unread,
Nov 10, 2005, 12:49:59 AM11/10/05
to
Ok, i have created a simple function which creates an instance of Excel
application.

======================================================================
function speak {
param([string] $text = "Hello, World!")

$private:ex = new-object -com excel.application
$private:ex.speech.speak($text, $null, $null, $null)

$private:ex.Quit()
# $private:ex = $null
}

MSH> speak "hello, friggin', world..."
======================================================================

After invoking "speak" function, "Excel.exe" shows up in TaskManager and
Excel.exe wouldn't go away even after "$private:ex.Quit()" although
$local:ex should be out of scope by the time "speak" has finished executing.

I have also tried to set "$private:ex" to $null but it didn't seem to
work so i just commented it out for now.

How could i dispose the Excel object?(or any other objects created
through COM interop? such as Word, or Outlook or Crystal reports, etc...)

Jouko Kynsijärvi

unread,
Nov 12, 2005, 11:25:25 AM11/12/05
to
dontBotherMeWithSpam wrote:
> ======================================================================
> function speak {
> param([string] $text = "Hello, World!")
>
> $private:ex = new-object -com excel.application
> $private:ex.speech.speak($text, $null, $null, $null)
>
> $private:ex.Quit()
> # $private:ex = $null
> }
>
>> speak "hello, friggin', world..."
> ======================================================================
>
> After invoking "speak" function, "Excel.exe" shows up in TaskManager
> and Excel.exe wouldn't go away even after "$private:ex.Quit()"
> although $local:ex should be out of scope by the time "speak" has
> finished executing.

You can release the COM object by using Marshal.ReleaseComObject():

$excel = new-object -com Excel.Application
$excel.Speech.Speak("hello", $null, $null, $null)
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$excel)

Note that without the [System.__ComObject] cast, it gives an error:

Exception calling "ReleaseComObject" with "1" argument(s): "The object's
type must be __ComObject or derived from __ComObject.


DontBotherMeWithSpam

unread,
Nov 12, 2005, 12:24:40 PM11/12/05
to
That solution works like a charm. I have never thought of disposing an
object that way.
Thank you.

Keith Hill

unread,
Nov 12, 2005, 12:55:39 PM11/12/05
to
"Jouko Kynsijärvi" <jouko.ky...@nospam.nospam> wrote in message
news:%23pf9pW6...@TK2MSFTNGP14.phx.gbl...

>
> You can release the COM object by using Marshal.ReleaseComObject():
>

Keep in mind that if you marshal a COM object back and forth between
different COM servers and MSH, the ref count on the RCW can get bumped up
past 1. That means that if you really, really want to get rid of the COM
object you typically do this:

while
([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$excel)
-gt 0) {}

Essentially ReleaseComObject returns the new ref count and you want to
continue calling it until the ref count reaches 0. At least this was the
way it worked in .NET 1.1. And indeed the .NET 2.0 docs say:

Note
To ensure that the runtime callable wrapper and the original COM
object are released, construct a loop from which you call this method until
the returned reference count reaches zero.

Yeah I've been bit by this issue before.

--
Keith


DontBotherMeWithSpam

unread,
Nov 12, 2005, 5:21:24 PM11/12/05
to
Uhm, so basically using the "loop" to check if there is no reference to
the object is left is a simple "work around" to problems they have with
ref counting?
Ah, anyways, using the loop to dispose objects works fine as well.

I guess I am going to have to keep this matter in mind when I mess
around with COM objects.
Thanks guys.

0 new messages