I have a small utility function in one PowerShell script:
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())
}
Am I supposed to clean-up the COM objects within the script? Or is PowerShell smart enough to automatically garbage COM Objects?
I've read Getting Rid of a COM Object (Once and For All) and blindly applied:
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($zip)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($target)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)
But I'm not sure if this was needed.
What the correct pattern of using COM objects in local functions?
Usually I use this function:
function Release-Ref ($ref) {
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) | out-null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
because I've noted that my comobject always stay alive, I think Powershell 2.0 is not able to remove comobject no more used.
[System.Runtime.InteropServices.Marshal]::ReleaseComObject( $ref )
(see here) return the new value of the reference count of the RCW associated with object. This value is typically zero since the RCW keeps just one reference to the wrapped COM object regardless of the number of managed clients calling it.
I've noted that for shell.application you need to call it until this value becomes 0.
To test if all references are released you can try, when value is 0, to read the value of $shell: it returns an error..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With