Many times while authoring PowerShell scripts, the expected output will be incorrect because PowerShell ISE does not automatically cleanup it’s variable between manual runs of a script. In my experience this poses two practical issue which lead to incorrect script results:
1) If the variable is not explicitly re-initialized in the script (very common practice), the script will be initialized with a value from the previous run, and,
2) If a script is changed so that a variable is not properly assigned a value, PowerShell ISE will still show the value from the previous run because it has not been assigned a new value since
This all leads to confusion. I’ve been trying to find the best way to clear all the variables a script has set a value for without restarting PowerShell ISE.
I am not particular happy with what I’ve come up with, but suffice to say, so far, this seems to be the easiest and quickest method:
Remove-Variable * -ErrorAction SilentlyContinue; Remove-Module *; $error.Clear(); Clear-Host
Here is a shorter version using aliases:
rv * -ea SilentlyContinue; rmo *; $error.Clear(); cls
** Note: this will indiscriminately remove ANY variables set during your PowerShell ISE session – not just the ones specific to the script you are working on.
Microsoft MVP Pat Richards has a similar approach which analyses the actual .ps script file to identify and remove only the variables used in the script. He wraps this in a function which can be invoked at anytime: https://www.ucunleashed.com/247.
function Remove-ScriptVariables($path) {
$result = Get-Content $path |
ForEach {if ( $_ -match ‘(\$.*?)\s*=’) {
$matches[1] | ? { $_ -notlike ‘*.*’ -and $_ -notmatch ‘result’ -and $_ -notmatch ‘env:’}
}}
ForEach ($v in ($result | Sort-Object | Get-Unique)) {
Write-Host “Removing” $v.replace(“$”,””)
Remove-Variable ($v.replace(“$”,””)) -ErrorAction SilentlyContinue
}}
# end function Get-ScriptVariables
For reasons I cannot figure out, Remove-Variable does not always remove all the variables for me using this function; but I like the approach.
So here is another method that works well:
- At the start of your script, include this line which gets the state of the variables before the script is run:
- $DefaultVariables = $(Get-Variable).Name
- Then at the end of your script, do a comparison and remove all of the variables added:
- ((Compare-Object -ReferenceObject (Get-Variable).Name -DifferenceObject $DefaultVariables).InputObject).foreach{Remove-Variable -Name $_}
This seems to work consistently the best.