When running PowerShell scripts at the console, scoping helps keep script variables from bleeding into the global environment. However, this seems to not quite apply in the PowerShell ISE. Thus, I've been trying to come up with an easy method to track variables in a script so they can be cleaned up whenever the script exits. A test script I've written to demonstrate this is below:
# Start from clean screen.
Clear-Host
# Set initial variables.
$Var1 = 1
$Var2 = 2
$Var3 = 3
# Initialize variables list.
$VarsList = New-Object System.Collections.ArrayList
# Function to add a variable.
function NewVar
{
$VarsList.Add($Args) | Out-Null
}
# Add initial variables to $VarsList.
'Var1','Var2','Var3' | ForEach-Object {NewVar $_}
# Check VarsList
Write-Host "VarsList:"
$VarsList
Write-Host ""
# Add a new variable to test NewVar.
$Var4 = 4
NewVar Var4
# Check VarsList
Write-Host "VarsList after Var4:"
$VarsList
Write-Host ""
# Function to remove variable from environment and variables list.
function KillVar
{
Remove-Variable $Args -Scope 1
$VarsList.Remove($Args[0])
}
# Function to remove all variables.
function VarGenocide
{
$VarsList | ForEach-Object {Remove-Variable $_ -Scope 1}
Remove-Variable VarsList -Scope 1
}
# Try to use KillVar
KillVar Var3
# Check Variables
Write-Host "Variables after KillVar Var3:"
Write-Host "Var1 $Var1"
Write-Host "Var2 $Var2"
Write-Host "Var3 $Var3"
Write-Host "Var4 $Var4"
Write-Host ""
# Check $VarsList
Write-Host "VarsList after KillVar Var3:"
$VarsList
Write-Host ""
# Try to remove all variables
VarGenocide
# Check Variables
Write-Host "Variables after VarGenocide:"
Write-Host "Var1 $Var1"
Write-Host "Var2 $Var2"
Write-Host "Var3 $Var3"
Write-Host "Var4 $Var4"
Write-Host ""
# Check $VarsList
Write-Host "VarsList after VarGenocide:"
$VarsList
Getting the variables removed doesn't seem to be a problem. However, updating $VarsList
for removed variables, appears to be more difficult than I'd anticipated. Here's the output of the above script.
As you can see, 'Var3'
was not removed from $VarsList
when I used KillVar
. This resulted in the "Cannot find a variable" error when VarGenocide
was attempted.
I have a feeling this has something to do with variable scoping. However, I'm not sure how to properly handle it since I'm not using PowerShell's built-in array class (see here for why). Am I right, and is there a way to work around this? Or is there another problem I'm not seeing?
I'm using PowerShell 4.0 on Windows 8.1, though I'm pretty sure this should be valid down to 2.0 on XP.