2013-09-26 106 views
4

我有一個小工具功能於一體PowerShell腳本:PowerShell中釋放COM對象

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

我認爲你找到的文章可能是正確的。對「Remove-Variable」的註釋進一步閱讀以釋放對變量的任何其他引用,然後GC可能會處理其餘的部分。如果你的對象有一個'Dispose()'方法,你也可以調用它(在釋放之前)。 – alroc

回答

1

我通常使用此功能:

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)返回與對象相關聯的RCW的引用計數的新值。該值通常爲零,因爲RCW只保留對被包裝的COM對象的一個​​引用,而不管被調用的被管理客戶端的數量。 我注意到,對於shell.application,您需要調用它直到此值變爲0.

要測試是否所有引用都已釋放,您可以嘗試在值爲0時讀取$ shell的值:它返回一個錯誤..

+0

如果我的對象被正確清除,有沒有辦法「監視」? –

+0

通常我使用辦公自動化,我只是看相對過程(即excel.exe),如果不再存在,但與shell.application我有一些懷疑它的工作... –

+1

我相信'ReleaseComObject'是鍵。我也相信另外兩條線不是強制性的。對於C#,我總是讀到最好在決定時讓GC工作。我會在PS中保留這個建議。 –