Archive | January, 2012

Removing a Global Variable from the PowerShell environment

26 Jan

UPDATE: It appears that this fix only works when called from the commandline. InvocationPoint.MyCommand.Definition is populated with the script that called it initially. Back to the drawing board for another solution.

Update 11/9/13: Added source code highlighting; typo fixes

Situation:

I had created a custom PowerShell module to use to log activity in other scripts I was writing. The module exposes a function that outputs a custom PSObject to hold the messages. In my scripts, I assigned this PSObject to a global function so it was available to other scripts I might call. At the end of the script, I wanted a method to close or remove the variable the the PSObject was assigned to so that it wouldn’t cause issues on the subsequent runs.

Issue:

The problem I ran into is there isn’t an easy way for removing the variable holding the PSObject. Trying to set $this = $null in the module doesn’t null out the containing object but the $this variable instead. Attempting to remove the variable with the Remove-Variable and $this also failed. My temporary solution was to iterate through all of the NoteProperty’s that were set and $null them out individually. This worked for a while, but required me to close and reopen the ISE between running scripts as the next attempt to run a script caused PowerShell to complain that it couldn’t add to the log variable.

Solution:

I finally tired of having to reopen the ISE and decided to fix my problem properly. The following is my solution:

function Get-VariableName{ 
    param() 
    $tmpRegex = '(?<=$[A-Z,a-z,0-9]*:).*(?=(s=|=))' 
    $this.InvocationPoint.MyCommand.Definition -match $tmpRegex | Out-Null 
    return $Matches[0].Trim() 
}

…

# Close # 
$tmpObject | Add-Member -MemberType ScriptMethod -Name Close ` 
    -Value { 
        param() 
        Remove-Item -Path "Variable:$(Get-VariableName)" 
}

The Get-VariableName uses regex to parse the variable name from the InvocationPoint of $this. The property $this.InvocationPoint.MyCommand.Definition exposes the full command used to create the variable. This was the only place I could find this information exposed in the object itself without adding a property. Now that I had the variable name, I used the Remove-Item function to remove the variable. That is probably the long way of removing instead of just using:

Remove-Variable –Name $(Get-VariableName) –Scope Global

Somehow I overlooked that command when I implemented the fix.

This works for now, but I may need to update the regex at some point to support both global and none global variables as I believe it will fail to capture none global variables. Fortunately I only use this with globally defined variables.

Advertisements