Главная > Powershell > Динамические параметры в Powershell

Динамические параметры в Powershell

Иногда при разработке функций возникает такая ситуация, когда какие-то параметры должны быть доступны только при указании какого-либо другого параметра, или когда когда какой-то параметр имеет определённое значение.

Например, возьмём простенькую функцию из одной из предыдущий статей для сбора некой информации о ПК. Если функция запускается в доменной сети пользователем, обладающим правами администратора домена (или любым другим пользователем имеющим достаточный уровень доступа) то функция нормально отработает. Если же в сети присутствует компьютер, не входящий в домен, то для доступа к этому компьютеру потребуется указать учётные данные, т.е. понадобится параметр, который в Powershell обычно называется –Credential.

В таких случаях на помощь приходят динамические параметры.

Справку по динамическим параметрам можно получить командой

Get-Help about_Functions_Advanced_Parameters

или почитать в онлайне.

Документация описывает динамические параметры как “параметры командлета, функции или скрипта, доступные только при определенных условиях”. Также отмечается, что динамические параметры используются “только тогда, когда другой параметр используется в команде или функции, или когда другой параметр имеет определенное значение”.

Для создания динамического параметра функции или скрипта используется ключевое слово DynamicParam.

Синтаксис выглядит следующим образом:

DynamicParam {<список_инструкций>}

В списке инструкций используется инструкция if для указания условий, при которых параметр будет доступен в функции.

Т.е для нашего примера описание динамического параметра может выглядеть так:

DynamicParam
{
    if ($ComputerName -eq "server")
    {
        # Создаём параметр Credential
    }
}

Для того, чтобы создать динамический параметр нужно создать объект System.Management.Automation.RuntimeDefinedParameter, который будет представлять этот параметр.

Также можно указать атрибуты этого объекта при помощи объекта System.Management.Automation.ParameterAttribute.

Поддерживаются следующие атрибуты:

HelpMessage                     string HelpMessage {get;set;}
HelpMessageBaseName             string HelpMessageBaseName {get;set;}
HelpMessageResourceId           string HelpMessageResourceId {get;set;}
Mandatory                       bool Mandatory {get;set;}
ParameterSetName                string ParameterSetName {get;set;}
Position                        int Position {get;set;}
ValueFromPipeline               bool ValueFromPipeline {get;set;}
ValueFromPipelineByPropertyName bool ValueFromPipelineByPropertyName {get;set;}
ValueFromRemainingArguments     bool ValueFromRemainingArguments {get;set;}

Возвращаясь к нашему примеру, нам нужно создать атрибуты для параметра, определяющего учётные данные –Credential. Допустим, нам нужно, чтобы наш параметр был обязательным и  стоял на втором месте:

$Attributes = New-Object System.Management.Automation.ParameterAttribute
$Attributes.Position = 2
$Attributes.Mandatory = $true
$Attributes.HelpMessage = "Пожалуйста, введите учётные данные"

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

# Создаём коллекцию атрибутов для объекта, который мы только что создали
$AttributeCollection =
    New-Object System.Collections.ObjectModel.Collection[System.Attribute]
# Добавляем наши атрибуты в коллекцию
$AttributeCollection.Add($Attributes)

Теперь, когда у нас есть атрибуты и коллекция можно создавать сам параметр.

Как уже говорилось выше для этого используем объект System.Management.Automation.RuntimeDefinedParameter, который предназначен для добавления параметра в список параметров функции (или командлета). Конструктору этого объекта нужно передать имя, тип и атрибуты параметра:

$Param =
    New-Object System.Management.Automation.RuntimeDefinedParameter(
        'Credential',
        [System.Management.Automation.PSCredential],
        $AttributeCollection)

Прежде чем мы сможем использовать наш объект его нужно добавить в пространство выполнения (runspace). Для этого используем объект RuntimeDefinedParameterDictionary. И в конце концов возвращаем наше творение:

$paramDictionary =
    New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
$paramDictionary.Add('Credential', $Param)

return $ParamDictionary

Собирая в единое целое все вышеописанные действия получаем:

DynamicParam
{
  if ($ComputerName -eq "server")
  {
     # Создаём атрибуты динамического параметра
     $Attributes = New-Object System.Management.Automation.ParameterAttribute
     $Attributes.Position = 2
     $Attributes.Mandatory = $true
     $Attributes.HelpMessage = "Пожалуйста, введите учётные данные"

     # Создаём коллекцию атрибутов для объекта, который мы только что создали
     $AttributeCollection =
        New-Object System.Collections.ObjectModel.Collection[System.Attribute]
     # Добавляем наши атрибуты в коллекцию
     $AttributeCollection.Add($Attributes)

     # Добавляем наш параметр
     $Param =
          New-Object System.Management.Automation.RuntimeDefinedParameter(
          'Credential',
          [System.Management.Automation.PSCredential],
          $AttributeCollection)

     # Добавялем наш параметр в коллекцию параметров
     $ParamDictionary =
       New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
     $ParamDictionary.Add('Credential', $Param)
        
        return $ParamDictionary
    }
}

В общем на этом всё.

В теле функции описание динамических параметров располагается там же, где и обычных параметров – перед действиями, выполняемыми функцией (чтобы не загромождать и без того как мне кажется запутанную статью я вырезал описание динамического параметра, приведённое выше):

Function Get-ComputerInfo
{
    [CmdletBinding()]
    param
    (
        [Parameter(
            Position=1,
            HelpMessage="Укажите имя компьютера"
        )]
        [string]$ComputerName
    )
 
    DynamicParam
    {
        # Описание динамического параметра
    }
    
    Process
    {
        $User = Get-WmiObject Win32_ComputerSystem @PSBoundParameters |
            Select-Object -ExpandProperty UserName
        $OS = Get-WmiObject Win32_OperatingSystem @PSBoundParameters |
            Select-Object -ExpandProperty CSName
            
        "`nПользователь:`t$User"
        "Имя компьютера:`t$OS `n"
    }
}

При вызове функции Get-ComputerInfo будет молча собираться информация об указанном компьютере. Если указано имя компьютера server, то функция потребует ввести пароль для доступа к этому компьютеру.

Чтобы ещё больше не запутывать текст не стал расписывать, но на всякий случай напомню, что @PSBoundParameters это один из вариантов использования сплаттинга.

Наверное, я выбрал не самый простой пример для демонстрации, но хотелось рассмотреть вариант поближе к жизни. Вот здесь рассматривается пример попроще, где в качестве динамического параметра выступает не объект Credential, а простое число.

Реклама
Рубрики:Powershell Метки: ,
  1. Комментариев нет.
  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: