How do I implement output variables in powershell?

I realize that "output variables" is probably the wrong terminology, so my google search failed me. I'm guessing it revolves around an explicitly defined variable scope, but I've tried reading the about_Scopes doc and it just didn't click on me.

Basically, I am trying to implement the equivalent of the argument -SessionVariable

from Invoke-RestMethod in my own module function.In other words, I need a string parameter that turns into a variable in the call scope.

function MyTest
{
    param([string]$outvar)

    # caller scoped variable magic goes here
    set-variable -Name $outvar -value "hello world"

    # normal function output to pipeline here
    Write-Output "my return value"
}

# calling the function initially outputs "my return value"
MyTest -outvar myvar

# referencing the variable outputs "hello world"
$myvar

      

For bonus points, how does things change (if at all) if I wrap an existing function that has its own output variable and I want to effectively pass the name of the output variable?

function MyWrapper
{
    param([string]$SessionVariable)

    Invoke-RestMethod -Uri "http://myhost" -SessionVariable $SessionVariable

    # caller scoped variable magic goes here
    set-variable -Name $SessionVariable -value $SessionVariable
}

# calling the wrapper outputs the normal results from Invoke-RestMethod
MyWrapper -SessionVariable myvar

# calling the variable outputs the WebRequestSession object from the inner Invoke-RestMethod call
$myvar

      

PS If it matters I am trying to keep the module Powershell v3 + compatible.

+3


source to share


2 answers


@Mathias R. Jessen offers a solution that works well if not defined in a module. But not if you put it in a module. So, I provide another solution that works when it is placed in a module.

In an extended function (using an attribute [CmdletBinding()]

) you can use $PSCmdlet.SessionState

to refer to the SessionState

caller. So you can use $PSCmdlet.SessionState.PSVariable.Set('Name' ,'Value')

to set variables in caller SessionState

.



Note. This solution will not work if it is not defined in the module or if it is called from the same module where it is defined.

New-Module {
    function MyTest1 {
        [CmdletBinding()]
        param([string]$outvar)
        $PSCmdlet.SessionState.PSVariable.Set($outvar, 'Some value')
    }
    function MyTest2 {
        [CmdletBinding()]
        param([string]$outvar)
        # -Scope 1 not work, because it executed from module SessionState,
        # and thus have separate hierarchy of scopes
        Set-Variable -Name $outvar -Value 'Some other value' -Scope 1
    }
    function MyTest3 {
        [CmdletBinding()]
        param([string]$outvar)
        # -Scope 2 will refer to global scope, not the caller scope,
        # so variable with same name in caller scope will hide global variable
        Set-Variable -Name $outvar -Value 'Some other value' -Scope 2
    }
} | Out-Null

& {
    $global:a = 'Global value'
    MyTest1 a
    $a
    $global:a
    ''
    MyTest2 a
    $a
    $global:a
    ''
    MyTest3 a
    $a
    $global:a
}

      

+4


source


There is no need to try to implement this yourself, -OutVariable

the General option is .

Add CmdletBinding

an attribute
to your block param

to get them for free:

function MyTest {
    [CmdletBinding()]
    param()

    return "hello world"
}

MyTest -OutVariable testvar

      

$testvar

now contains the string value "hello world"



For your second example, where you need to set a value in the call scope in addition to the output pipeline, use the -Scope

c parameter Set-Variable

:

function MyTest {
    [CmdletBinding()]
    param([string]$AnotherVariable)

    if([string]::IsNullOrWhiteSpace($AnotherVariable)){
        Set-Variable -Name $AnotherVariable -Value 'more data' -Scope 1
    }

    return "hello world"
}

MyTest -AnotherVariable myvar

      

$myvar

in the call area now contains the string value "more data". The value 1

passed to the parameter Scope

means "1 level up"

+7


source







All Articles