无法在Powershell中修改函数参数

时间:2011-11-10 14:16:50

标签: function powershell arguments

我有一个与此类似的功能:

function A-Function{
  [CmdletBinding(SupportsShouldProcess=$True)]
param (
    [Parameter(Position=0, HelpMessage="A Test string", Mandatory=$true)]
    [string]$Path,

    [Parameter(Position=1, HelpMessage="The list of file names to download.", ValueFromPipeline=$True)]
    [string[]]$testVar,

    [Parameter(HelpMessage= "The username")]
    [string]$User,

    [Parameter(HelpMessage= "The password")]
    [string]$Password,

    [Parameter(HelpMessage= "The credentials used.")]
    [Net.NetworkCredential]$Credential = (New-Object Net.NetworkCredential("Anonymous", ""))
)

Begin {         
    $Path = "TEST_" + $Path

    if ($User) {
        if ($Password) {
            $Credential = New-Object Net.NetworkCredential($User, $Password)
        }
    }
}

Process {
    $Path
    $Credential
}

End {

}

}

如果我运行“A-Function test -User test -Password -test”,我会得到输出:

TEST_test

UserName密码SecurePassword域
-------- -------- -------------- ------
测试测试System.Security.SecureString

这就是我对输出的预期。但是,如果我改为运行此命令:

  

“测试”| A-Function测试-User test -Password -test

我得到了这个输出:

TEST_test

UserName密码SecurePassword域
-------- -------- -------------- ------
匿名System.Security.SecureString

换句话说,在第二个场景中,它没有在Begin部分中更改Credential参数的值,但在第一个场景中它没有。我不明白为什么会这样,有人可以解释一下吗?

此致

2 个答案:

答案 0 :(得分:3)

如果你做了

trace-command parameterbinding {"Test" | A-Function test -User test -Password test} -pshost

你会看到$ credential,因为它没有作为参数传递给函数,所以每次process期间都会使用默认值绑定。另一方面,路径只绑定一次,因为您将其传递给函数,因此您在开始时所做的更改在过程中可用。

这绝对是一个错误/不是最佳的错误,因为这不会在Powershell v3中重现。在v3中,您将获得所需的凭证输出,而不是匿名。

您现在可以解决此问题,当然,在开始时使用局部变量或使用$script:Path等确定现有变量:

function A-Function{
  [CmdletBinding(SupportsShouldProcess=$True)]
param (
    [Parameter(Position=0, HelpMessage="A Test string", Mandatory=$true)]
    [string]$Path,

    [Parameter(Position=1, HelpMessage="The list of file names to download.", ValueFromPipeline=$True)]
    [string[]]$testVar,

    [Parameter(HelpMessage= "The username")]
    [string]$User,

    [Parameter(HelpMessage= "The password")]
    [string]$Password,

    [Parameter(HelpMessage= "The credentials used.")]
    [Net.NetworkCredential]$Credential = (New-Object Net.NetworkCredential("Anonymous", ""))
)

Begin {         
    $script:Path = "TEST_" + $Path

    if ($User) {
        if ($Password) {
            $script:Credential = New-Object Net.NetworkCredential($User, $Password)
        }
    }
}

Process {
    $script:Path
    $script:Credential
}

End {

}
}

"Test" | A-Function test -User test -Password test

答案 1 :(得分:1)

是的,我被这个咬了。每次迭代Process块时,函数参数都会重置。只需在Begin块中设置一个局部变量,然后在Process块中使用该局部变量,而不是使用参数变量。

编辑:

我必须承认我对你的示例代码并不是很认真,因为我立刻发现了问题标题和你在Begin块中设置$ Path这一事实的问题。更难看一下你的函数,让我想知道为什么当你不处理任何管道输入时你有一个Process块。

我的回忆是,您对Begin块中的函数参数所做的更改将在Process块的第一次迭代后继续存在。它们只会在后续迭代中重置(或者,也许在第一次迭代结束时)。