powershell 查找ValidateSet中的值

nlejzf6q  于 2023-02-04  发布在  Shell
关注(0)|答案(3)|浏览(110)

我想知道是否有一种方法可以为ValidateSet检索子句Param()中使用的值。

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

    $Type.ValidateSet
}

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

0sgqnhkj

0sgqnhkj1#

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

    $ParameterList = (Get-Command -Name $MyInvocation.MyCommand).Parameters
    $ParameterList["Type"].Attributes.ValidValues
}

在您的评论之后:

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

(Get-Variable "Type").Attributes.ValidValues

Get-Variable调用也可以在函数中使用。

wlzqhblo

wlzqhblo2#

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

    • 最强大的解决方案**,应适用于任何调用情形,PSv2 +
param (
    [ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
    [String]$Type = 'Startup'
)

# -> @('Startup', 'Shutdown', ...)
($MyInvocation.MyCommand.Parameters['Type'].Attributes |
  Where-Object { $_ -is [ValidateSet] }).ValidValues
    • 更简单但可能脆弱的PSv3 +**解决方案,假定
  • Set-StrictMode或者被设置为-Version 1或者不被设置。
      • Set-StrictMode的设置可能超出您的控制范围**,因此如果您不能完全控制执行环境,则使用上面更详细的PSv2兼容命令会更安全。

(The Set-StrictMode设置的行为类似于变量:它被派生作用域 * 继承 *,但是在派生作用域中设置它会 * 本地 * 设置它(只影响 * 那个 * 作用域和 * 它的 * 派生)。

  • 然而:
  • 您可以在脚本/函数 * 的开头显式运行Set-StrictMode -OffSet-StrictMode -Version 1,尽管您可能希望在之后恢复所需的值。无论您设置的模式如何,都会影响后代作用域。请注意, 没有 * 方法 * 查询 * 当前有效的严格模式。
  • 如果将函数定义为module的一部分,则外部的Set-StrictMode设置 * 不 * 适用。
  • 当重复 * 点源 * 脚本时,运行到this bug(从PowerShell 7.3.1起仍然存在)不是问题。
param (
    [ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
    [String]$Type = 'Startup'
)

# Assumes that at most Set-StrictMode -Version 1 is in effect.
# You could explicitly run Set-StrictMode -Off or Set-StrictVersion -Version 1 
# in here first.
(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或更高值会导致尝试访问不存在的特性以引发错误,并且命令 * fails *。

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

通过显式定位已知具有.ValidValues属性的一个感兴趣的属性(使用-is运算符按类型标识它),可以绕过此问题。
使用(Get-Variable Type).Attributes访问参数[variable] $Type的属性的更详细的替代方法是使用$MyInvocation.MyCommand.Parameters['Type'].Attributes
使用$MyInvocation.MyCommand.Parameters集合可以枚举和检查 * 所有 * 参数,而无需事先知道它们的名称。
David Brabant's answer很有帮助,但是(在撰写本文时):

  • 它可能会给人一种错误的印象,以为脚本和函数需要不同的方法。
  • Get-Command -Name $MyInvocation.MyCommand部分为:
    • 不必要 *,因为$MyInvocation.MyCommand * 本身 * 提供了感兴趣的信息:

$MyInvocation.MyCommand是 * scripts * 中的类型[System.Management.Automation.ExternalScriptInfo]和 * functions * 中的类型[System.Management.Automation.FunctionInfo]的示例,这两个类型都派生自类型[System.Management.Automation.CommandInfo][System.Management.Automation.CommandInfo]Get-Commmand返回的类型-因此它们不仅提供相同的信息,而且还 * 明确地 * 引用封闭的脚本/函数。

    • 易碎 *:
  • $MyInvocation.MyCommand由于被传递给-Name参数而被转换为 * 字符串 *,这在 * 脚本 * 中导致脚本的 * 纯文件名 *(例如script.ps1),并且在 * 函数 * 中导致函数的 * 名称 *(例如Foo)。
  • 在 * script * 中,这通常会导致Get-Command根本找不到脚本-除非脚本恰好在PATH中($env:PATH中列出的目录之一)。但这也意味着一个 * 不同的 * 脚本,恰好具有相同的文件名,并且恰好在PATH中的第一个,可能会匹配,产生不正确的结果。

简而言之:脚本中的Get-Command -Name $MyInvocation.MyCommand经常会 * break *,当它返回结果时,可能是针对错误的脚本。

  • 在 * function * 中,它也可以识别错误的命令,尽管这种可能性要小得多:

由于PowerShell's command precedence,一个给定的名字首先被解释为一个 * alias *,然后被解释为一个 * function *,所以理论上,如果定义了一个Foo * alias ,那么在 * function * Foo中的Get-Command -Name $MyInvocation.MyCommand将错误地返回关于 * alias * 的信息。
(It在定义别名Foo时,
invoke * 函数Foo并不简单,但可以做到;例如:& (Get-Item Function:Foo)

x9ybnkn6

x9ybnkn63#

validateScript,可以提供更灵活的解决方案,如果您需要额外的参数验证,它会很好地工作。这还允许您通过创建get-validTypes函数来获取foo函数之外的有效参数列表。

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"
    }

}

相关问题