如何在PowerShell中实现输出变量?

时间:2017-04-10 19:11:41

标签: powershell powershell-v3.0

我意识到"输出变量"这可能是错误的术语,这就是为什么我的谷歌搜索失败了我。我猜它是围绕明确设置变量范围,但我已经尝试阅读about_Scopes文档而且它没有点击给我。

基本上我尝试做的是在我自己的模块函数中实现Invoke-RestMethod-SessionVariable参数的等价物。换句话说,我需要一个字符串参数,该参数在调用者的范围内变成一个变量。

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

对于奖励积分,如果我包装具有自己的输出变量的现有函数并且我想有效地通过输出变量名称,事情如何改变(如果有的话)?

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

P.S。如果重要,我试图让模块与Powershell v3 +保持兼容。

2 个答案:

答案 0 :(得分:7)

您无需亲自尝试实现此目标,-OutVariableCommon Parameter

param区块添加CmdletBinding attribute以免费获取这些内容:

function MyTest {
    [CmdletBinding()]
    param()

    return "hello world"
}

MyTest -OutVariable testvar

$testvar现在保存字符串值“hello world”

对于第二个示例,除了管道输出之外,还需要在调用者范围中设置值,请使用-Scope选项和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现在包含字符串值“more data”。传递给1参数的Scope值表示“1级别”

答案 1 :(得分:4)

@Mathias R. Jessen提出了解决方案,该方法在模块中未定义时效果很好。但不是,如果你把它放在模块中。所以,我提供了另一个解决方案,当放入模块时可以工作。

在高级功能(使用[CmdletBinding()]属性的功能)中,您可以使用$PSCmdlet.SessionState来引用来电者的SessionState。因此,您可以使用$PSCmdlet.SessionState.PSVariable.Set('Name' ,'Value')在来电者SessionState中设置变量。

注意:如果未在模块中定义或者从定义的同一模块调用此解决方案,则此解决方案将无效。

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
}