1

I've created the following function for use cleaning up all references to com objects at the end of a script:

function TrashCompactor ($reflist) {

foreach ($ref in $Reflist){



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

[Runtime.InteropServices.Marshal]::FinalReleaseComObject($ref) | out-null

Remove-Variable $ref | out-null

}


[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

}

Will Remove-variable work as I expected? Is there any harm to including [System.GC]::Collect()?

1
  • There is no point in calling Remove-Variable inside a function on a local variable such as $ref, because it will go out of scope automatically when the function is exited; aside from that, you have to pass the name of the variable (ref), not its value ($ref) - ergo: Remove-Variable $ref; also, Remove-Variable never produces (success) output, so there's no point in piping it to Out-Null. Commented Mar 7, 2020 at 4:19

1 Answer 1

1

Yes, and no... as this...

[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

... is a common and best practice.

Windows will always do a cleanup, but it's always clean up your environment when you are done.

As documented...

Clean Up Your PowerShell Environment by Tracking Variable Use https://devblogs.microsoft.com/scripting/clean-up-your-powershell-environment-by-tracking-variable-use

And covered by this SO Q&A and accepted answer...

PowerShell release COM object

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 )

and that SO is exactly what you are asking, so this question is really a duplicate.

My example, I use a prefix to my variable so they are easy to find and simple globally clean up.

# Assign results to a variable and output to the screen using variable squeezing
($ponMyShell = New-Object -com "Wscript.Shell")
($ponDate = Get-Date)
($ponProcess = Get-Process |
    Select -First 3)

<#
# Results

Monday, 2 March, 2020 19:40:47

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                                                                                              
-------  ------    -----      -----     ------     --  -- -----------                                                                                                              
    186      14     2648       6800       0.14  15336   0 aesm_service                                                                                                             
    465      27    24300      34064       0.33  27612  22 ApplicationFrameHost                                                                                                     
    158       8     1928       4848       0.02  14268   0 AppVShNotify 

SpecialFolders     CurrentDirectory   
--------------     ----------------   
System.__ComObject C:\Windows\system32
#>

Get-Variable -Name 'pon*'
<#
# Results 

Name                           Value                                                                                                                                               
----                           -----                                                                                                                                               
ponDate                        02-Mar-20 19:46:59                                                                                                                                  
ponMyShell                     System.__ComObject                                                                                                                                  
ponProcess                     {System.Diagnostics.Process (aesm_service), System.Diagnostics.Process (ApplicationFrameHost), System.Diagnostics.Process (AppVShNotify)} 
#>


# Clear resource environment
Get-PSSession |
Remove-PSSession
<#
# Results

#>

[System.Runtime.InteropServices.Marshal]::
ReleaseComObject([System.__ComObject]$ponMyShell) |
Out-Null
<#
# Results

#>

[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
<#
# Results

#>

Get-Variable -Name 'pon*' |
ForEach { Get-Variable -Name $_ |
    Remove-Variable -Force }

# Validate clean-up
Get-Variable -Name 'pon*'

<#
# Results


#>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.