Недавно стояла задача написать скрипт, в котором были бы разные параметры для разных сценариев применения данного скрипта. Например, если указан параметр Param1 выполнять одно действие, если указан Param2 выполнять другое действие, но вместе Param1 и Param2 указываться не могут. Для решения данной задачи идеально подходят так называемые наборы параметров в PowerShell. Вот о них и пойдет речь в этой статье.
Param1 или Param2
Я уже рассказывал о параметризованных скриптах в своей статье скрипты PowerShell. Рекомендую с ней ознакомиться, если Вы не знакомы с возможностью PowerShell писать скрипты с параметрами.
Давайте рассмотрим такую задачу нашему скрипту необходимо брать данные либо из файла, либо из параметра. В моем случае это был список виртуальных машин, он мог хранится в файле, а так же его можно было задавать через параметры скрипта.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[CmdletBinding()] Param ( [parameter(Mandatory=$true)] [string]$Folder, [parameter(ParameterSetName="VirtualMachineByName",ValueFromPipeline=$true)] [string[]]$VirtualMachines = $null, [parameter(ParameterSetName="VirtualMachineFromFile")] [switch]$FromFile, [string]$Network, [switch]$Export ) $psCmdlet.ParameterSetName |
В этом примере мы видим 5 параметров Folder, VirtualMachines, FromImportFile, Network, Export. Параметр VirtualMachines будет использоваться только в наборе параметров VirtualMachineByName, а параметр FromFile будет использоваться в наборе параметров VirtualMachineFromFile. Таким образом одновременное использование этих параметров будет невозможно. Все остальные параметры можно будет использовать в любом из наборов параметров.
Давайте я сохраню данный скрипт под именем temp.ps1 и запущу справку к нему.
1 2 3 |
PS C:\> Get-Help .\temp.ps1 temp.ps1 -Folder <string> [-VirtualMachines <string[]>] [-Network <string>] [-Export] [<CommonParameters>] temp.ps1 -Folder <string> [-FromFile] [-Network <string>] [-Export] [<CommonParameters>] |
Как видно справка отображает два варианта запуска, где отчетливо видно что доступен только один из вариантов запуска. Вы можете запустить данный скрипт с разными параметрами и выяснить какой из наборов параметров был использован.
Param1 или Param2 или ни одного из них
К сожалению, вышеприведенный скрипт не реализует еще один из необходимых мне сценариев. Скрипт должен запускаться и без данных параметров. Фактически это означает что необходим третий сценарий, в котором будут отсутствовать оба из этих параметров.
И тут есть два варианта или мы добавляем третий параметр или обходимся без него. Меня добавление еще одного параметра не устраивало. Поэтому в вызов CmdletBinding я добавил DefaultParameterSetName и значение All.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[CmdletBinding(DefaultParameterSetName="All")] Param ( [parameter(Mandatory=$true)] [string]$Folder, [parameter(ParameterSetName="VirtualMachineByName",ValueFromPipeline=$true)] [string[]]$VirtualMachines = $null, [parameter(ParameterSetName="VirtualMachineFromFile")] [switch]$FromFile, [string]$Network, [switch]$Export ) $psCmdlet.ParameterSetName |
Данный подход указал, что по умолчанию будет использоваться набор параметров All. У меня он не используется, поэтому все те параметры, у которых не указан явно набор параметров будут относится к набору параметров All. Справка это подтверждает.
1 2 3 4 |
PS C:\> Get-Help .\temp.ps1 temp.ps1 -Folder <string> [-Network <string>] [-Export] [<CommonParameters>] temp.ps1 -Folder <string> [-VirtualMachines <string[]>] [-Network <string>] [-Export] [<CommonParameters>] temp.ps1 -Folder <string> [-FromFile] [-Network <string>] [-Export] [<CommonParameters>] |
Напоследок
Если необходимо указать сразу несколько наборов параметров для одного параметра, то это нужно делать так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[CmdletBinding(DefaultParameterSetName="All")] Param ( [parameter(Mandatory=$true)] [string]$Folder, [parameter(ParameterSetName="VirtualMachineByName",ValueFromPipeline=$true)] [string[]]$VirtualMachines = $null, [parameter(ParameterSetName="VirtualMachineFromFile")] [switch]$FromFile, [parameter(ParameterSetName="VirtualMachineByName")] [parameter(ParameterSetName="VirtualMachineFromFile")] [string]$Network, [switch]$Export ) $psCmdlet.ParameterSetName |
В данном примере параметр Network используется только для наборов параметров VirtualMachineByName и VirtualMachineFromFile. О чем говорит справка:
1 2 3 4 |
PS C:\> Get-Help .\temp.ps1 temp.ps1 -Folder <string> [-Export] [<CommonParameters>] temp.ps1 -Folder <string> [-VirtualMachines <string[]>] [-Network <string>] [-Export] [<CommonParameters>] temp.ps1 -Folder <string> [-FromFile] [-Network <string>] [-Export] [<CommonParameters>] |
Почитать напоследок
Блог MSDN — Fun With Parameter Binding: The Fake Parameter Set Trick
Справка MSDN — Наборы параметров