11

我在一个 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 对象?

我已经阅读了摆脱 COM 对象(一劳永逸)盲目应用:

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

但我不确定这是否需要。

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

4

2 回答 2

10

通常我使用这个功能:

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 )

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

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

于 2013-09-26T13:43:23.303 回答
0

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

于 2018-10-01T18:43:01.600 回答