如何使Powershell validatescript参数从数组中提取?

时间:2019-05-13 15:47:05

标签: arrays powershell validateset

我有一个具有许多高级功能的模块。 我需要使用一长串ValidateSet参数。 我想将所有可能的参数列表放在一个数组中,然后在函数本身中使用该数组。 如何从数组中提取整个列表?

New-Variable -Name vars3 -Option Constant -Value @("Banana","Apple","PineApple")
function TEST123 {
    param ([ValidateScript({$vars3})]
    $Fruit)
    Write-Host "$Fruit"
}

问题在于,当我使用该函数时,它不会从常量中提取内容。

TEST123 -Fruit 

如果我指定常量的索引值,那么它将起作用。

TEST123 -Fruit $vars3[1] 

它返回苹果。

2 个答案:

答案 0 :(得分:1)

您误解了ValidateScript ...

  

ValidateScript验证属性

     

ValidateScript属性指定一个脚本,该脚本用于   验证参数或变量值。 PowerShell将值传递给   脚本,如果脚本返回$ false或   该脚本将引发异常。

     

当您使用ValidateScript属性时,该值是   validated映射到$ _变量。您可以使用$ _变量来引用脚本中的值。

...有效。正如其他人到目前为止所指出的。您没有使用脚本,而是在使用静态变量。

要获得我相信的追求,您可以通过这种方式做到。

(注意,由于在PowerShell中默认输出到屏幕,因此也不需要Write-。即使这样,也要避免使用Write-Host,除非在目标场景中,例如使用color屏幕输出。即使如此,您也不需要它。可以使用几个cmdlet,并且可以更灵活地获得颜色。请参阅下面列出的MS powershelgallery.com模块)*

Find-Module -Name '*Color*'

调整发布的代码,并结合Ansgar Wiechers所显示的内容。

$ValidateSet =   @('Banana','Apple','PineApple') # (Get-Content -Path 'E:\Temp\FruitValidationSet.txt')

function Test-LongValidateSet
{
    [CmdletBinding()]
    [Alias('tlfvs')]

    Param
    (
        [Validatescript({
            if ($ValidateSet -contains $PSItem) {$true}
            else { throw $ValidateSet}})]
        [String]$Fruit
    )

    "The selected fruit was: $Fruit"
}

# Results - will provide intellisense for the target $ValidateSet
Test-LongValidateSet -Fruit Apple
Test-LongValidateSet -Fruit Dog


# Results

The selected fruit was: Apple

# and on failure, spot that list out. So, you'll want to decide how to handle that

Test-LongValidateSet -Fruit Dog
Test-LongValidateSet : Cannot validate argument on parameter 'Fruit'. Banana Apple PineApple
At line:1 char:29

只需将其添加到文本数组/文件中,但这也意味着该文件必须位于您使用此代码的每个主机上,或者至少能够到达UNC共享位置。

现在,您可以使用其他记录的“动态参数验证集”。 Lee_Daily会指向您进行查找,但这要花上更长的时间。

示例:

function Test-LongValidateSet
{
    [CmdletBinding()]
    [Alias('tlfvs')]

    Param
    (
        # Any other parameters can go here
    )

    DynamicParam
    {
        # Set the dynamic parameters' name
        $ParameterName = 'Fruit'

        # Create the dictionary 
        $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

        # Create the collection of attributes
        $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]

        # Create and set the parameters' attributes
        $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
        $ParameterAttribute.Mandatory = $true
        $ParameterAttribute.Position = 1

        # Add the attributes to the attributes collection
        $AttributeCollection.Add($ParameterAttribute)

        # Generate and set the ValidateSet 
        $arrSet = Get-Content -Path 'E:\Temp\FruitValidationSet.txt'
        $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)

        # Add the ValidateSet to the attributes collection
        $AttributeCollection.Add($ValidateSetAttribute)

        # Create and return the dynamic parameter
        $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
        $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
        return $RuntimeParameterDictionary
    }

    begin
    {
        # Bind the parameter to a friendly variable
        $Fruit = $PsBoundParameters[$ParameterName]
    }

    process
    {
        # Your code goes here
        $Fruit
    }

}

# Results - provide intellisense for the target $arrSet
Test-LongValidateSet -Fruit Banana
Test-LongValidateSet -Fruit Cat

# Results

Test-LongValidateSet -Fruit Banana
Banana

Test-LongValidateSet -Fruit Cat
Test-LongValidateSet : Cannot validate argument on parameter 'Fruit'. The argument "Cat" does not belong to the set "Banana,Apple,PineApple" 
specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:29

再次,只需将文本添加到文件中,这又意味着,该文件必须位于使用此代码的每个主机上,或者至少能够到达UNC共享位置。< / p>

答案 1 :(得分:1)

我不确定您的用例是什么,但是如果您使用的是PowerShell 5.x或更高版本,则另一种可能性是创建一个类,或者如果您使用的是旧版本,则可以嵌入一些用代码中的C#创建可以使用的枚举:


Add-Type -TypeDefinition @"
   public enum Fruit
   {
      Strawberry,
      Orange,
      Apple,
      Pineapple,
      Kiwi,
      Blueberry,
      Raspberry
   }
"@

Function TestMe {
  Param(
    [Fruit]$Fruit
  )

  Write-Output $Fruit
}