我想知道是否有办法检索Param()
条款ValidateSet
中使用的值。这样的事情会很棒:
Function Foo {
Param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
$Type.ValidateSet
}
但当然Type
对象上没有这样的属性。是否可以检索ValidateSet
中设置的值?
答案 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"
}
}