Использование расширенных наборов параметров в функции с несколькими уникальными переключателями

3422
cyborgcommando0

Я использую Powershell 4.0.

Я пытаюсь написать командлет, и в этом командлете я хотел бы использовать расширенные наборы параметров, чтобы были доступны определенные параметры в зависимости от того, какие параметры выбраны. Эта конкретная функция по сути и в конечном итоге будет Get-ADComputer, но с -SearchBase, предварительно запрограммированным для определенных опций.

У меня всего 6 параметров. 2 - строки ($ ComputerName или $ IpAddress), 1 - целое число ($ OULevel) и 3 переключателя ($ ComputerOU, $ AllCompany, $ List).

У меня есть набор параметров для ComputerName и IPAddress, я хотел бы, чтобы пользователь мог вводить один или другой - я думаю, что я понял это довольно просто. Тем не менее, я хотел бы, чтобы $ OULevel, $ ComputerOU и $ AllCompany были исключительными, если одно используется, другое не должно использоваться. Список $ должен оставаться доступным в каждом сценарии.

Я пробовал разные варианты наборов параметров безрезультатно. Вот как сейчас выглядит мой сценарий с некоторой обрезанной спиной:

 function Get-CompanyADComputer{ [CmdletBinding(DefaultParametersetName="ComputerName")]  Param( [Parameter(Mandatory=$true, ParameterSetName="ComputerName", Position=0, ValueFromPipeline=$false, HelpMessage='Enter a computer name to search in ActiveDirectory.')] [Alias('Computer','CN')] [string]$ComputerName,  [Parameter(Mandatory=$true, ParameterSetName="IPAddress", Position=0, ValueFromPipeline=$false, HelpMessage='Enter an IP address to search in ActiveDirectory.')] [Alias('IPv4Address','IPv6Address')] [string]$IPAddress,  [Parameter(Mandatory=$false, HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')] [ValidateRange(0,8)] [int]$OULevel = 0,  [Parameter()] [Switch]$ComputerOU,  [Parameter()] [Switch]$AllCompany,  [Parameter()] [Switch]$List ) 

Если вам интересно, что наша AD организована по местоположению, затем по категории (компьютер, пользователь, группы, контакты и т. Д.), А затем она становится более детальной в каждом подразделении ниже. Этот скрипт обнаруживает OU вашего компьютера и начинает поиск там. Цель $ OULevel - если пользователь указывает другое число, поиск начинается в другом OU, а затем выполняется рекурсивный поиск. Цель $ ComputerOU состоит в том, чтобы поиск выполнялся в подразделении «Компьютеры по умолчанию» вместо всего домена или вашего местоположения. Целью $ AllCompany является использование поиска по умолчанию для всего домена вместо любого другого выбора или OU.

Любое руководство приветствуется. Кажется, я не смогу овладеть этим без того, чтобы мой сценарий не был полностью запутанным.

2

2 ответа на вопрос

2
cyborgcommando0

Я спросил у дона Джонса гуру powershell на другом форуме, и он дал мне информацию, которая мне была нужна. Он объяснил мне это, сказав следующее:

Если я понимаю вопрос, то вам, в принципе, нужно учесть все возможные комбинации. Помните, что параметр может принадлежать 1+ наборам параметров. Таким образом, у вас может быть набор с Computername и OULevel, Computername и ComputerOU, а также Computername и AllCompany. Это три. Затем эти три снова для IP-адреса. Я знаю, что это не элегантно, но посмотрите на помощь для Where-Object - тоже не элегантно. Список тогда не принадлежал бы набору, а это значит, что он принадлежал бы всем.

Это поставило меня на правильный путь. Поэтому я фактически изменил способ работы моего командлета, поэтому мой ответ был переработан, но теперь, когда я понимаю, что делать, я обновлю свой существующий пример, чтобы быть последовательным и, надеюсь, помочь.

 function Get-CompanyADComputer{ [CmdletBinding(DefaultParametersetName="ComputerName")]  Param( [Parameter(Mandatory=$true, ParameterSetName="ComputerName", Position=0, ValueFromPipeline=$false, HelpMessage='Enter a computer name to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="ComputerNameOULevel", Position=0, ValueFromPipeline=$false, HelpMessage='Enter a computer name to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="ComputerNameComputerOU", Position=0, ValueFromPipeline=$false, HelpMessage='Enter a computer name to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="ComputerNameAllCompany", Position=0, ValueFromPipeline=$false, HelpMessage='Enter a computer name to search in ActiveDirectory.')] [Alias('Computer','CN')] [string]$ComputerName,  [Parameter(Mandatory=$true, ParameterSetName="IPAddress", Position=0, ValueFromPipeline=$false, HelpMessage='Enter an IP address to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="IPAddressOULevel", Position=0, ValueFromPipeline=$false, HelpMessage='Enter an IP address to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="IPAddressComputerOU", Position=0, ValueFromPipeline=$false, HelpMessage='Enter an IP address to search in ActiveDirectory.')] [Parameter(Mandatory=$true, ParameterSetName="IPAddressAllCompany", Position=0, ValueFromPipeline=$false, HelpMessage='Enter an IP address to search in ActiveDirectory.')] [Alias('IPv4Address','IPv6Address')] [string]$IPAddress,  [Parameter(Mandatory=$false, ParameterSetName="ComputerNameOULevel", HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')] [Parameter(Mandatory=$false, ParameterSetName="IPAddressOULevel", HelpMessage='Enter a number between 0 and 8. 0 is your current OU Container.')] [ValidateRange(0,8)] [int]$OULevel = 0,  [Parameter(ParameterSetName="ComputerNameComputerOU")] [Parameter(ParameterSetName="IPAddressComputerOU")] [Switch]$ComputerOU,  [Parameter(ParameterSetName="ComputerNameAllCompany")] [Parameter(ParameterSetName="IPAddressAllCompany")] [Switch]$AllCompany,  [Parameter()] [Switch]$List ) 

Поскольку я не хотел, чтобы эти 3 параметра использовались друг с другом, они должны принадлежать их собственным наборам параметров, поэтому при попытке использовать один параметр другие не будут отображаться в качестве опции. Это очень помогает и упрощает сам процесс написания сценариев. Вместо того чтобы позволить самому сценарию учитывать пользовательский ввод, наборы параметров Powershell исключают эти параметры.

Параметр $ List не имеет имени набора параметров, потому что я хочу, чтобы этот параметр был доступен в каждом сценарии.

0
beatcracker

Вот код, который использует DynamicParameters и функцию New-DynamicParameter для их создания:

# DotSource New-DynamicParameter function . '.\New-DynamicParameter.ps1'  function Get-CompanyADComputer { [CmdletBinding(DefaultParametersetName = 'ComputerName_AllCompany')] Param() DynamicParam { $BaseParameters = @( @{ Name = 'ComputerName' Type = [string] Mandatory = $true ParameterSetName = 'ComputerName' HelpMessage = 'Enter a computer name to search in ActiveDirectory.' Alias = 'Computer', 'CN' }, @{ Name = 'IPAddress' Type = [System.Net.IPAddress] Mandatory = $true ParameterSetName = 'IPAddress' HelpMessage = 'Enter an IP address to search in ActiveDirectory.' Alias = 'IPv4Address', 'IPv6Address' } )  $MutuallyExclusiveParameters = @( @{ Name = 'OULevel' HelpMessage = 'Enter a number between 0 and 8. 0 is your current OU Container.' ValidateRange = 0, 8 Type = [int] } @{ Name = 'ComputerOU' Type = [switch] }, @{ Name = 'AllCompany' Type = [switch] } )  $AllParamSetParameters = @( @{ Name = 'List' Type = [switch] } )  $DynamicParameters = ( # For each base parameter $BaseParameters | ForEach-Object { # Iterate over mutually exclusive parameters $MutuallyExclusiveParameters | ForEach-Object -Begin {$BaseParam = $_} -Process { # Generate new ParameterSet name: Base parameter ParameterSetName + mutually exclusive parameter name $CurrParamSetName = '_' -f $BaseParam.ParameterSetName, $_.Name  # Clone base parameter, so we modify copy of it $NewBaseParam = $BaseParam.Clone() # Set its ParameterSetName $NewBaseParam.ParameterSetName = $CurrParamSetName  # Clone mutually exclusive parameter, so we modify copy of it $NewMEParam = $_.Clone() # Set its ParameterSetName $NewMEParam.ParameterSetName = $CurrParamSetName  # Output new base parameter and new mutually exclusive parameter $NewBaseParam $NewMEParam } } ) + $AllParamSetParameters # Add parameters that should exist in all parameter sets  # Create and output new dynamic parameters $DynamicParameters | ForEach-Object | New-DynamicParameter }  Process { # Dynamic parameters don't have corresponding variables created, # you need to call New-DynamicParameter with CreateVariables switch to fix that. New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters  # Show all parameters $PSBoundParameters | Format-Table -AutoSize -HideTableHeaders | Out-String  <#  Your code here...  #> }  }