Functions from Module Scoping Question

Welcome Forums General PowerShell Q&A Functions from Module Scoping Question

This topic contains 2 replies, has 2 voices, and was last updated by

 
Participant
4 years, 7 months ago.

  • Author
    Posts
  • #14216

    Participant
    Points: 0
    Rank: Member

    Hello Power Users 🙂

    I have the following case:

    I`m using module that contains several functions, some of them are executing commends in remote sessions. These functions are used from Powershell Script.
    The issue is that when function refers to variable from the local computer using the "$Using:var" syntax, it does not tries to access the variables that is defined in Script scope.
    The exception is:
    "Invoke-Command : The value of the using variable '$using:var' cannot be retrieved because it has not been set in the local session."

    This behavior is not reproduced when the functions are defined in the Script. I`m aware that Modules have their own "Scope"(or Context or whatever...), so I suppose the behavior is by design 🙂

    I`m able to workaround it in two ways:
    Using the "$Using:global:var" syntax in the script block or dot source the script.

    However it`s not so appropriate for my purpose.

    My Question is:
    Can I force the Functions that comes from Module to behave the same way as if they are defined in the Script.
    Any other suggestions are welcome.

    Some examples:

    Module content:
    ————————————————————————————–
    function Main
    {

    param
    (
    $sb2
    )

    $ses = New-PSSession -ComputerName sof-srv01

    Execute -ses $ses -sb $sb2

    }

    function Execute
    {

    param (
    $sb,
    $ses
    )

    Invoke-Command -Session $ses -ScriptBlock $sb

    }

    Export-ModuleMember Execute,Main
    ————————————————————————————–

    Script content:
    ————————————————————————————–
    $var = 'winrm'
    $scr = {Get-Service $using:var}

    Main -sb2 $scr
    ————————————————————————————–

  • #14223

    Member
    Points: 0
    Rank: Member

    Ideally, you should pass in $var as a parameter to your module function. It's cleanest if any input required by a function is defined as a parameter, and any output is returned via the output stream (or reference parameters.)

    That said, there are some situations where you need to be able to read variables from the caller's scope, and Script Modules do not automatically inherit those variables in the current versions of PowerShell. I've blogged about this a couple of times, and have a function to address it posted on the TechNet Gallery:

    Revisited: Script Modules and Variable Scopes

    Getting your Script Module functions to inherit "Preference" variables from the caller


    http://gallery.technet.microsoft.com/Inherit-Preference-82343b9d

    I've also submitted an article on this topic for the Hey, Scripting Guy blog, and in the course of reviewing it, I learned that the PowerShell team would consider this to be a design bug in Script Modules. At their suggestion, I submitted a bug report on the Connect site, but it will need to get quite a few "up" votes before it's likely to be addressed. https://connect.microsoft.com/PowerShell/feedback/details/828782/functions-in-script-modules-do-not-inherit-variables-from-the-scope-of-their-caller

    Anyhow, if you decide not to pass $var in to your function as a parameter, then you could use the Get-CallerPreference function (third link I posted in this thread) as follows, at the beginning of your module function:

    Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState -Name var
    

    At which point, you'd have a $var variable defined inside your module function's scope, with the same value as the caller.

  • #14256

    Participant
    Points: 0
    Rank: Member

    Thank you Dave!

The topic ‘Functions from Module Scoping Question’ is closed to new replies.