PowerShell发布COM对象

时间:2013-09-26 13:35:46

标签: powershell

我在一个PowerShell脚本中有一个小实用程序函数:

function Unzip-File{
    param(
        [Parameter(Mandatory=$true)]
        [string]$ZipFile,
        [Parameter(Mandatory=$true)]
        [string]$Path
    )

    $shell=New-Object -ComObject shell.application

    $zip = $shell.namespace($ZipFile)
    $target = $shell.NameSpace($Path)
    $target.CopyHere($zip.Items())
}

我是否应该清理脚本中的COM对象?或者PowerShell足够智能自动垃圾COM对象?

我已经阅读了Getting Rid of a COM Object (Once and For All)盲目

[System.Runtime.Interopservices.Marshal]::ReleaseComObject($zip)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($target)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)

但我不确定是否需要这样做。

在本地函数中使用COM对象的正确模式是什么?

2 个答案:

答案 0 :(得分:4)

通常我会使用这个功能:

function Release-Ref ($ref) {

[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) | out-null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

}

因为我注意到我的comobject总是活着,我认为Powershell 2.0无法删除不再使用的comobject。

[System.Runtime.InteropServices.Marshal]::ReleaseComObject( $ref )

(参见here)返回与object关联的RCW的引用计数的新值。此值通常为零,因为RCW只保留对包装的COM对象的一个​​引用,而不管调用它的受管客户端的数量。 我已经注意到,对于shell.application,您需要调用它,直到此值变为0。

要测试是否所有引用都已释放,当值为0时,您可以尝试读取$ shell的值:它会返回错误..

答案 1 :(得分:0)

GC适用于.NET对象,而不适用于.NET包装的COM对象。您需要显式清理底层的COM对象。