我在一个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对象的正确模式是什么?
答案 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对象。