1

In Single Module Scenario: Running Set-Var returns 10.

# m.psm1

function Set-Var {
    $MyVar = 10
    Get-Var
}

function Get-Var {
    $MyVar
}

In Nested Modules Scenario: Running Set-Var does not return any value.

# m1.psm1

function Get-Var {
    $MyVar
}
# m.psm1

Import-Module .\m1.psm1

function Set-Var {
    $MyVar = 10
    Get-Var
}

How do I achieve the same effect as a single module with nested modules? Using $script:MyVar also does not work. However, I would like to keep the scope of the variable local to enable concurrent executions with different values.

Navaneeth P
  • 1,428
  • 7
  • 13
  • I guess then you should be using parameters to the functions, otherwise $MyVar is just a local variable ($null) inside each of the functions – Theo May 25 '22 at 14:01

1 Answers1

4

Your code doesn't work because local variables are not inherited by functions in nested module context.

You can do this instead:

$null = New-Module {
    function Get-Var {
        [CmdletBinding()] param()
        $PSCmdlet.SessionState.PSVariable.Get('MyVar').Value
    }
}
  • The New-Module command creates an in-memory module, because this code only works when the caller is in a different module or script.
  • Use the CmdletBinding attribute to create an advanced function. This is a prerequisite to use the automatic $PSCmdlet variable, which we need in the next step.
  • Use its SessionState.PSVariable member to get or set a variable from the parent (module) scope.
  • This answer shows an example how to set a variable in the parent (module) scope.
  • See also: Is there any way for a powershell module to get at its caller's scope?
zett42
  • 25,437
  • 3
  • 35
  • 72
  • Tested this out. It gets the variable from the immediate parent. Since, we get access to the parent's PSCmdlet also, we can keep moving to the previous caller. Is there a way to do the same if the caller is in the same module? I saw your other post with Get-Variable -scope 1. Any way to do that in C# directly without an invocation? – Navaneeth P May 25 '22 at 17:06
  • @NavaneethP What do you mean by "Any way to do that in C# directly without an invocation?". Do you mean a compiled cmdlet written in C#? – zett42 May 25 '22 at 17:30
  • Yes. Compiled cmdlet written in C#. GetVariableValue and SessionState.PSVariable.GetValue don't have a scope parameter. – Navaneeth P May 26 '22 at 01:06
  • @NavaneethP Sorry, can't help with that. I've never written compiled cmdlet. – zett42 May 26 '22 at 09:57