Найти значения в ValidateSet
Мне было интересно, если есть способ получить значения, используемые в предложении Param()
за ValidateSet
, Примерно так было бы здорово
Function Foo {
Param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String]$Type = 'Startup'
)
$Type.ValidateSet
}
Но, конечно, на Type
объект. Можно ли получить значения, установленные в ValidateSet
?
3 ответа
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
Вызов также работает в функции.
Все приведенные ниже решения работают как в функциях, так и в сценариях.
Самое надежное решение, которое должно работать в любом сценарии вызова, 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-совместимую команду, описанную выше.
(TheSet-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
Дополнительная справочная информация
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
имущество.
Более подробная альтернатива для доступа к атрибутам параметра [variable] $Type
с (Get-Variable Type).Attributes
это использовать $MyInvocation.MyCommand.Parameters['Type'].Attributes
,
Использование $MyInvocation.MyCommand.Parameters
коллекция позволяет перечислять и проверять все параметры без необходимости заранее знать их имена.
Ответ Дэвида Брабанта полезен, но (на момент написания статьи):
Это может создать ошибочное впечатление, что для сценариев и функций необходимы отдельные подходы.
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)
)
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"
}
}