我想知道是否有检索子句中使用的值的方式Param()进行ValidateSet.像这样的东西会很棒:
Function Foo {
Param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
$Type.ValidateSet
}
Run Code Online (Sandbox Code Playgroud)
但当然Type对象上没有这样的属性.是否可以检索设置的值ValidateSet?
function Foo {
param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
$ParameterList = (Get-Command -Name $MyInvocation.MyCommand).Parameters
$ParameterList["Type"].Attributes.ValidValues
}
Run Code Online (Sandbox Code Playgroud)
你的评论后:
param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
(Get-Variable "Type").Attributes.ValidValues
Run Code Online (Sandbox Code Playgroud)
该Get-Variable调用也适用于函数.
以下所有解决方案均可在功能和脚本中使用.
最强大的解决方案应该适用于任何调用方案,PSv2 +:
param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
($MyInvocation.MyCommand.Parameters['Type'].Attributes |
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues
Run Code Online (Sandbox Code Playgroud)
一个更简单但易碎的PSv3 +解决方案,它假定:
即Set-StrictMode要么设置-version 1或不设置.
Set-StrictMode可能已设置在您的控件之外,因此如果您不完全控制执行环境,则使用上面更详细的PSv2兼容命令会更安全.
(该Set-StrictMode设置的行为类似于变量:它由后代作用域继承,但在后代作用域中设置它会在本地设置它(仅影响该作用域及其后代).)
但是,如果你定义一个函数作为的一部分模块,外界的Set-StrictMode设置不会不适用.
至少至少Windows PowerShell v5.1/PowerShell Core v6.0-alpha16,在重复点源脚本时遇到此错误并不是一个问题.
param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
(Get-Variable Type).Attributes.ValidValues
Run Code Online (Sandbox Code Playgroud)
PSv3 +速记语法(Get-Variable Type).Attributes.ValidValues基本上相当于:
(Get-Variable Type).Attributes | ForEach-Object { $_.ValidValues }
Run Code Online (Sandbox Code Playgroud)
也就是说,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
Run Code Online (Sandbox Code Playgroud)
通过明确地定位已知具有属性的一个感兴趣的属性(使用-is运算符来按类型识别)来绕过此问题.ValidValues.
于访问参数[变量]的属性的更详细的替代$Type用(Get-Variable Type).Attributes是使用$MyInvocation.MyCommand.Parameters['Type'].Attributes.
使用该$MyInvocation.MyCommand.Parameters集合可以枚举和检查所有参数,而无需事先知道其名称.
David Brabant的回答很有帮助,但(撰写本文时):
它可能会产生错误的印象,即脚本和函数需要单独的方法.
该Get-Command -Name $MyInvocation.MyCommand部分是:
不必要的,因为$MyInvocation.MyCommand 它本身提供相关信息:
$MyInvocation.MyCommand是类型的实例[System.Management.Automation.ExternalScriptInfo]在脚本和类型[System.Management.Automation.FunctionInfo]的功能,这两者从类型派生[System.Management.Automation.CommandInfo],这是该类型Get-Commmand返回-所以他们不仅提供相同的信息,他们也明确请参阅附带的脚本/功能.
脆的:
$MyInvocation.MyCommand被转换成字符串,由于被传递给至-Name参数,其在脚本导致脚本的单纯的文件名(例如,script.ps1),和在一个功能中的功能的名称(例如,Foo).
在脚本中,这通常会导致Get-Command根本找不到脚本 - 除非该脚本恰好位于PATH(其中列出的目录之一$env:PATH)中.但这也意味着碰巧具有相同文件名且恰好在PATH中首先出现的不同脚本可能会匹配,从而产生不正确的结果.
简而言之:Get-Command -Name $MyInvocation.MyCommand在脚本中经常会中断,当它确实返回结果时,它可能是错误的脚本.
在函数中,它也可以识别错误的命令,尽管这种可能性要小得多:
由于PowerShell的命令优先级,给定的名称首先被解释为别名,然后作为函数,理论上,定义了Foo 别名,Get-Command -Name $MyInvocation.MyCommand内部函数 Foo会返回错误有关的信息的别名.
(这是平凡到调用函数Foo,而别名Foo定义,但它可以做到的;例如:& (Get-Item Function:Foo))
| 归档时间: |
|
| 查看次数: |
1382 次 |
| 最近记录: |