question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`Get-Variable -Scope <number>` should (possibly) return the (inherited) read scope

See original GitHub issue

Summary of the new feature / enhancement

As a user I would expect the Get-Variable -Scope <number> to return the (inherited) read scope of the concerned variable. (or at least have an easy way to do so with e.g. an extra parameter.)

function Child {
    Write-Host 'Parent DebugPreference:' (Get-Variable 'DebugPreference' -Scope 1 -ValueOnly)
}

function Parent {
    Write-Host 'Parent DebugPreference:' $DebugPreference
    Child
}
Parent

Expected:

Parent DebugPreference: SilentlyContinue
Parent DebugPreference: SilentlyContinue

Actual:

Parent DebugPreference: SilentlyContinue
Get-Variable: C:\Users\Gebruiker\Scripts\Test-Scope\Test-Scope.ps1:10
Line |
  10 |  … ebugPreference:' (Get-Variable 'DebugPreference' -Scope 1 -ValueOnly)
     |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find a variable with the name 'DebugPreference'.

Proposed technical implementation details (workaround)

function Child {
    for ($i = 1; $i -lt (Get-PSCallStack).Count; $i++) {
        $ParentDebugPreference = Get-Variable 'DebugPreference' -Scope $i -ValueOnly -ErrorAction SilentlyContinue
        if ($Null -ne $ParentDebugPreference) { break }
    }
    Write-Host 'Parent DebugPreference:' $ParentDebugPreference
}

function Parent {
    Write-Host 'Parent DebugPreference:' $DebugPreference
    Child
}
Parent

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:15

github_iconTop GitHub Comments

1reaction
jhoneillcommented, Sep 29, 2022

Anyways, I am still interested in your view of this issue, whether:

  • The default Get-Variable behavior could be considered incorrect

    • if yes, I presume the default behavior won’t change as is might be a considered as a break change even it currently generates an error in the case the variable isn’t (re)set in the concerned scope.
  • If Get-Variable could be fixed/improved with an extra parameter

I am trying to figure out what the actual requirement is and if you need to use get-variable at all. If you want the inherited $x won’t $x provide what you want in almost all cases ? Some example code to show why I think Get-Variable isn’t needed.

function a {
$x = 1 
"Local x in a is '$local:x' ; x is '$x'"
b
}

function b {
"Local x in b is '$local:x' ; x is '$x'"
c
}

function c {
"Local x in c is '$local:x' ; x is '$x'"
}

a
Local x in a is '1' ; x is '1'
Local x in b is '' ; x is '1'
Local x in c is '' ; x is '1'

This shows that in B and C, we can test for “X was (not) set locally”, “X has a value” therefore it’s simple to get to “X was inherited”, without caring where from If X is a parameter or a preference variable set via a parameter, I’m trying to think of a real-world use case for wanting to know what it was before it was set here. “$x from all higher scopes but not this one” is something I have never needed myself, so I’m having trouble imagining a use for it.

In a more complicated example.

function c {
## other code would be here
    if     ($local:x )    {"x was set in This function"}    
    elseif ($x -and     (Get-Variable -Name X -Scope 1 -ErrorAction SilentlyContinue) ) {
          "x was set in this function's parent"
    }
    elseif ($global:x ) {
          "x was set in the Global scope"
    }
    else  { "x was set higher than this functions parent but not globally"}
}

PS> a
Local x in a is '1' ; x is '1'
Local x in b is '' ; x is '1'
x was set higher than this functions parent but not globally

This shows an example where we don’t want the present behaviour of Get-Variable to change (we want to know if a variable was or was not set in scope 1) but maybe a “AND ABOVE” switch could be helpful - but as a I said my imagination isn’t giving me any cases.

As @SeeminglyScience says variables don’t inherit out of modules and I have a post about that, and how preference variables can be passed here:
https://devblogs.microsoft.com/powershell-community/how-to-have-more-control-of-preferences-in-functions-and-the-role-of-modules-on-inheritance/ it’s not clear from the question if you are trying to solve a problem with $DebugPreference but that post might help if you are.

<div> PowerShell Community</div><div>On Preferences and Scopes</div><div>Progress in PowerShell: a tale of Verbosity and other preferences with lessons in Scopes and Proxies thrown in It started, as these things often do, with someone complaining. In PowerShell Version 7.2 the output of Invoke-WebRequest -Verbose and Invoke-RestMethod -Verbose look like this: VERBOSE: GET with 0-byte payload In all the earlier versions they look like the version below,</div>
1reaction
SeeminglySciencecommented, Sep 28, 2022

The way I’d recommend implementing this is to place your function in a different module. e.g.

New-Module {
    function Log {
        [CmdletBinding()]
        param()
        end {
            # This won't be found
            $test = 'no'

            # `$PSCmdlet.SessionState` refers to the *caller's* session state
            $PSCmdlet.SessionState.PSVariable.Get('test')
        }
    }
} | Import-Module

$test = 'yes'
function Caller {
    Log
}

Caller
Read more comments on GitHub >

github_iconTop Results From Across the Web

about Scopes - PowerShell
A child scope doesn't inherit the variables, aliases, and functions from the parent scope. Unless an item is private, the child scope can...
Read more >
Building Better Scripts with PowerShell Scopes for Variables
A way to use scopes to reduce conflicts is to use the private scope. Using the private scope disables inheritance on that specific...
Read more >
Getting All Variables In Scope - javascript
@Jason - No, the question is clear. Inside a function the variables in scope will include global variables, this , arguments , parameters...
Read more >
Using flow variables | Apigee Edge
As you'll see, variables have scope, and where they are accessible depends in part on when they are created in the API proxy...
Read more >
Powershell Global Variable: Explained With Examples
In PowerShell, the variable scope is the area where a variable is ... To retrieve the value of a global variable, you can...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found