在ValidateSet中查找值

时间:2017-03-09 13:47:26

标签: powershell

我想知道是否有办法检索Param()条款ValidateSet中使用的值。这样的事情会很棒:

Function Foo {
    Param (
        [ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
        [String]$Type = 'Startup'
    )

    $Type.ValidateSet
}

但当然Type对象上没有这样的属性。是否可以检索ValidateSet中设置的值?

3 个答案:

答案 0 :(得分:6)

Get-Variable

发表评论后:

from os import linesep

with open("your_script_file", 'w') as f:
    f.write("your_data" + linesep)
    f.write("your_data_too" + linesep)

android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:ellipsize="marquee" 调用也适用于函数。

答案 1 :(得分:5)

以下所有解决方案都适用于 函数脚本。

最强大的解决方案应该适用于任何调用方案, PSv2 +

param (
    [ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
    [String]$Type = 'Startup'
)

($MyInvocation.MyCommand.Parameters['Type'].Attributes |
  Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues

更简单但更脆弱的PSv3 + 解决方案,假设

  • Set-StrictMode设置为-version 1或未设置。

    • Set-StrictMode可能已设置在您的控件之外,因此如果您不完全控制执行环境,则使用更详细的信息会更安全,上面的PSv2兼容命令。
      Set-StrictMode设置的行为类似于变量:后代作用域继承,但在后代作用域中设置本地(仅影响 范围和后代)。)

    • 但是,如果您将某个功能定义为module的一部分,则外部世界的Set-StrictMode设置适用。

  • 至少在Windows PowerShell v5.1 / PowerShell Core v6.0-alpha16上运行this bug时反复点源脚本不是问题。

    < / LI>
param (
    [ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
    [String]$Type = 'Startup'
)

(Get-Variable Type).Attributes.ValidValues

可选背景信息

PSv3 +速记语法(Get-Variable Type).Attributes.ValidValues基本上相当于:

(Get-Variable Type).Attributes | ForEach-Object { $_.ValidValues }

也就是说,PowerShell会自动枚举集合 .Attributes并收集每个元素的 .ValidValues属性的值。

在目前的情况下,只有.Attributes集合中的一个属性 - 子类型[System.Management.Automation.ValidateSetAttribute]之一 - 具有.ValidValues属性,因此单个返回值。

鉴于其他属性没有此类属性,将Set-StrictMode设置为-version 2或更高会导致尝试访问不存在的属性以引发错误,并且命令失败

((Get-Variable Type).Attributes |
  Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues

通过明确定位感兴趣的一个属性(使用-is运算符按类型识别)来解决此问题,该属性已知具有.ValidValues属性。

使用$Type访问参数[变量] (Get-Variable Type).Attributes的属性的更详细的替代方法是使用$MyInvocation.MyCommand.Parameters['Type'].Attributes

使用$MyInvocation.MyCommand.Parameters集合可以枚举和检查所有参数,而无需事先知道其名称。

David Brabant's answer很有帮助,但(截至撰写本文时):

  • 可能会产生错误的印象,即脚本和功能需要单独的方法。

  • Get-Command -Name $MyInvocation.MyCommand部分是:

    • 不必要的,因为$MyInvocation.MyCommand 本身提供了感兴趣的信息:
      $MyInvocation.MyCommand脚本[System.Management.Automation.ExternalScriptInfo]类型的实例,函数中的[System.Management.Automation.FunctionInfo]类型,两者都来自类型{{ 1}},这是[System.Management.Automation.CommandInfo]返回的类型 - 因此它们不仅提供相同的信息,而且明确地引用封闭的脚本/函数。

      • Get-Commmand由于被传递到$MyInvocation.MyCommand参数而被转换为字符串,在脚本中会导致脚本的仅仅是文件名(例如,-Name),以及函数名称中的功能 (例如,script.ps1)。

      • 脚本中,通常会导致Foo根本找不到脚本 - 除非该脚本恰好位于PATH中(Get-Command中列出的目录之一)。但这也意味着碰巧具有相同文件名且恰好在PATH中首先出现的不同的脚本可能会匹配,从而产生不正确的结果。
        简而言之:脚本中的$env:PATH通常会中断,当它确实返回结果时,它可能是错误的脚本。

      • 功能中,它也可以识别错误的命令,尽管这种可能性要小得多:
        由于PowerShell's command precedence,给定名称首先被解释为别名,然后被解释为函数,因此,理论上,Get-Command -Name $MyInvocation.MyCommand 别名已定义,功能 Foo内的Get-Command -Name $MyInvocation.MyCommand会错误地返回有关别名的信息。
        (定义别名Foo时,调用函数Foo非常重要,但可以完成;例如:Foo

答案 2 :(得分:0)

validateScript,可以提供更灵活的解决方案,并且如果您需要其他参数验证,则可以正常运行。这也允许您通过创建foo函数获取get-validTypes函数之外的有效参数列表。

Function Foo {
    Param (
        [validateScript({test-validTypes $_})]
        [String]$Type = 'Startup'
    )

    get-validTypes
}

function get-validTypes {

    $powerOptions = @('Startup', 'Shutdown', 'LogOn', 'LogOff')
    Write-Output $powerOptions

}

function test-validTypes {
[cmdletbinding()]
param ($typeInput)

    $validTypes = get-validTypes
    if ($validTypes.contains($typeInput)){
        return $true
    } else {
        Write-Error "Invalid Type Paramater, Must be on of the following: $powerOptions"
    }

}