相同的参数名称,不同的范围,相同的值。怎么处理?

时间:2018-01-28 19:22:15

标签: powershell

# cmdlet MyCmdlet.ps1
Param(
    [Parameter(Mandatory=$true)]
    [string]$Variable1,

    [string]$Variable2
)

Begin {
    Function Function-Name {
        Param (
            [Parameter(Mandatory=$true)]
            [string]$Variable1,

            [Parameter(Mandatory=$false)]
            [string]$Variable2,

            [Parameter(Mandatory=$false)]
            [ValidateScript({[string]::IsNullOrWhiteSpace($Variable2)})]
            [switch]$Choice
        )

        # function-body
    }
}

Process {
    Function-name -Variable1 "SomeString" -Choice
}

此cmdlet的调用方式如下:

.\MyCmdlet.ps1 -variable1 "string1" -variable2 "string2"

它返回:

  

无法验证参数' choice'的参数。 " [string] :: IsNullOrWhiteSpace($ Variable2)"参数的验证脚本,其值为#34; True"没有返回True的结果。

似乎cmdlet的-Variable2的值被隐式传递给函数,因为相同的变量名称,即使在cmdlet内部的函数调用期间没有特别提及它。

注意:我需要变量具有相同的名称,以便将来可以看到它们的相似功能。我在cmdlet中使用BeginProcessEnd,因此我可以将其转换为函数并放入其他脚本中。

我该如何处理?

2 个答案:

答案 0 :(得分:2)

ValidationScript运行时,尚未创建局部变量$Variable2,因此您从父作用域中的$Variable2获取值。

改为使用$PSBoundParameters

Function Function-Name {
    Param (
        [Parameter(Mandatory=$true)]
        [string]$Variable1,

        [Parameter(Mandatory=$false)]
        [string]$Variable2,

        [Parameter(Mandatory=$false)]
        [ValidateScript({[string]::IsNullOrWhiteSpace($PSBoundParameters['Variable2'])})]
        [switch]$Choice
    )

}

答案 1 :(得分:0)

如果你的目的是创建一个既可以直接调用(作为脚本)又可以点源调用的脚本(这样你就可以从其他PowerShell脚本中调用它中的函数),你可以这样做:

# Invoke-Something.ps1
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$false)]
    [string]$Variable1,

    [Parameter(Mandatory=$false, ParameterSetName='bar')]
    [string]$Variable2,

    [Parameter(Mandatory=$true, ParameterSetName='foo')]
    [switch]$Choice
)

function Invoke-Something {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)]
        [string]$Variable1,

        [Parameter(Mandatory=$false, ParameterSetName='bar')]
        [string]$Variable2,

        [Parameter(Mandatory=$true, ParameterSetName='foo')]
        [switch]$Choice
    )

    Write-Host 'invocation: function'
}

if ($MyInvocation.Line.Split()[0] -ne '.') {
    Write-Host 'invocation: directly'
    Invoke-Something @PSBoundParameters
} else {
    Write-Host 'invocation: dot-source'
}

使用上述方法,您可以直接调用脚本:

PS> Invoke-Something.ps1 -Variable1 'some' -Variable2 'other'
invocation: directly
invocation: function

或点源它并调用函数:

PS> . Invoke-Something.ps1
invocation: dot-source
PS> Invoke-Something -Variable1 'some' -Variable2 'other'
invocation: function

为此,您必须使脚本的所有参数都是可选的。

此简化版本不会在脚本级别定义参数并将@args传递给调用的函数:

# Invoke-Something.ps1

function Invoke-Something {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)]
        [string]$Variable1,

        [Parameter(Mandatory=$false, ParameterSetName='bar')]
        [string]$Variable2,

        [Parameter(Mandatory=$true, ParameterSetName='foo')]
        [switch]$Choice
    )

    Write-Host 'invocation: function'
}

if ($MyInvocation.Line.Split()[0] -ne '.') {
    Write-Host 'invocation: directly'
    Invoke-Something @args
} else {
    Write-Host 'invocation: dot-source'
}