codewario
codewario

Reputation: 21418

How to check the scope of a variable in Powershell

Is there a programmatic way to determine the scope of a variable in Powershell? After reading the about_scopes page it states to use Get-Variable, but in testing it seems the variable objects look the same, excepting the Name and Value:

# Script variable
$cool = 'nice'
Get-Variable cool | Select * # => Options     : None
                             #    Value       : nice
                             #    Name        : nice
                             #    Description : 
                             #    Visibility  : Public
                             #    Module      : 
                             #    ModuleName  : 
                             #    Attributes  : {}

# Child variable
function Test-Function {
  $dude = 'sweet'
  Get-Variable dude | Select-Object *
}
Test-Function # => Options     : None
              #    Value       : sweet
              #    Name        : dude
              #    Description :
              #    Visibility  : Public
              #    Module      :
              #    ModuleName  :
              #    Attributes  : {}

What I was thinking of doing was doing Get-Variable -Scope 0 (or 1) to check if a variable is declared in the current or parent scope, or against the Global, Local, or Script scopes, then finding the variable name in each scope starting with the lowest possible scope first, but I'm hoping there is a more graceful method of finding out where a variable was declared in a Powershell session.

Upvotes: 5

Views: 2061

Answers (1)

Alexey I. Kuzhel
Alexey I. Kuzhel

Reputation: 156

We can not see how many scope we have straight. Main idea is that we have scope count no more then Get-PSCallStack count plus 3.

Function Get-VariableScope {
    [CmdletBinding()]
    param(        
        [Parameter( Mandatory = $True, Position = 0, HelpMessage = "Variable name." )]
        [string] $VariableName,
        [Parameter( Mandatory = $false, Position = 1, HelpMessage = "Variable value.", ParameterSetName = 'Variable' )]
        $VariableValue,
        [Parameter( Mandatory = $false, Position = 2, HelpMessage = "Scope list.", ParameterSetName = 'Scope array' )]
        [switch] $ScopeArray
    )
    $Result = $null

    $ScopeList = (0..( ( Get-PSCallStack ).count + 2 ))
    $VariableScopeArray = @()
    foreach ( $Scope in $ScopeList ){
        try{
            $Res = Get-Variable -Name $VariableName -Scope $Scope -ErrorAction 'SilentlyContinue'
            if ( $Res ){
                $Res | Add-Member -NotePropertyName 'Scope' -NotePropertyValue $Scope
                $VariableScopeArray += $Res
            }
        }
        Catch{ }
        
    }

    if ( $ScopeArray ){
        $Result = $VariableScopeArray
    }
    else {
        $Result = ( $VariableScopeArray | Where-Object { $_.value -eq $VariableValue } ).scope
    }

    return $Result
}

To see the variable $Name scope number call Get-VariableScope -VariableName 'name' -VariableValue $Name To see all scopes variable in, call Get-VariableScope -VariableName 'name' -ScopeArray

Upvotes: 3

Related Questions