Используем параметры в функциях Powershell с param и Parameter


16 августа 2021


Как использовать param и Parameter в Powershell при создании функций

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

 

Где и как использовать param и Parameters

Создавая функции (команды) мы преследуем одну цель - сделать возможность использования какого-то кода многократным. С таким подходом следующая функция имеет право на жизнь:

function Test-Site{
   ping 8.8.8.8
}

Создание функции без параметров в Powershell

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

function Test-Site1{
   ping 8.8.8.8
}
function Test-Site2{
   ping 6.6.6.6
}

Такой подход нарушает один из основных принципов программирования DRY (dont repeat yourself). Его смысл простой - избегайте дублирование написанного кода. Дублирование кода понижает риск ошибок и дальнейшей поддержки. Это основной смысл функций.

Для соблюдения принципа DRY есть несколько вариантов.

Переменная args

В Powershell, так же как и во многих других языках, существует переменная 'args'. Смысл в этой переменной хранить все переданные значения в коллекции (так же называются списки, листы или просто массив).

Эта переменная создается автоматически при вызове команды:

function Test-Site1{
   Write-Host "Тип данных: $($args.GetType())"
   Write-Host "Переданные значения: $args"
}

Использование $args в команде Powershell

Что бы получать доступ к каждому значение мы должны обращаться к нему по индексу:

function Test-Array{
   Write-Host "Первый элемент: $($args[0])" -ForegroundColor Cyan
   Write-Host "Второй элемент: $($args[1])" -ForegroundColor DarkMagenta
}

Использование $args с индексами в функции Powershell

Одна из проблем, которая появляется при использовании '$args', неочевидность использования. Спустя время вы, или другой человек, можете не вспомнить про порядок передаваемых значений, их типы данных и т.д. Нужно будет открывать код и читать его что бы разобраться в этом.

Именованные параметры

Более очевидным способом передачи значений - использование именованных параметров. Мы присваиваем значение определенным ключам (параметрам). Такая реализация чаще всего применяется в создании функций.

Использование ключей выглядит так:

Test-NetConnection -ComputerName '8.8.8.8' -Hops 1

Работа именованных параметров в Powershell

Вряд ли у вас возникнут сомнения в том, что должно находится в параметре "ComputerName" или "Hops". Это нельзя гарантировать при использовании "$args".

Что бы реализовать параметры в вашей функции существует 2 подхода.

Первый способ похож на реализацию параметров в большинстве языков, мы просто помещаем их в круглые скобки:

function Test-Site($dest1,$dest2){
   ping $dest1
   ping $dest2
}
Test-Site -dest1 '8.8.8.8' -dest2 '6.6.6.6'

Принцип создания именованного параметра в Powershell

Второй способ реализуется через блок param() в котором мы объявляем параметры:

function Test-Site{
   param(
      $dest1,
      $dest2
   )
   ping $dest1
   ping $dest2
}
Test-Site -dest1 '8.8.8.8' -dest2 '6.6.6.6'

Принцип создания именованного параметра в Powershell с param

Оба примера отменяют возможность работы переменной "$args" - массив просто будет пустым.

Блок 'param' более предпочтительный способ. Он принят сообществом как стандарт передачи параметров. Кроме этого он позволяет использовать расширенный функционал.

Расширенные функции с CmdletBinding и Parameter

В Powershell есть понятие расширенных функций. Эти функции создаются при наличии одного или двух атрибутов: 'CmdletBinding ' и 'Parameter'. Благодаря им у вашей команды автоматически появляется следующий список ключей (указан ключ и алиас):

  • -Debug (-db)
  • -ErrorAction (-ea)
  • -ErrorVariable (-ev)
  • -InformationAction (-infa)
  • -InformationVariable (-iv)
  • -OutBuffer (-ob)
  • -OutVariable (-ov)
  • -PipelineVariable (-pv)
  • -Verbose (-vb)
  • -WarningAction (-wa)
  • -WarningVariable (-wv)

Атрибут 'CmdletBinding()' - может хранить в себе значения, которые касаются всей функции без привязки к конкретному параметру. В статье будут указаны некоторые его применения. Определяется этот атрибут до блока 'param':

function Get-Data{
   [CmdletBinding()]
   param(
      $Name
   )
   Write-Host $Name
}
Get-Data -Name 'Alex' -ErrorAction SilentlyContinue

Создание расширенной функции Powershell с cmdletbinding

Атрибут 'Parameter' используется внутри 'param'. Он используется для проверки (валидации) определенных параметров. Эти проверки могут быть разными: может ли ключ принимать данные с конвейера, какова его максимальна длина, является ли он обязательным и т.д. Блок 'Parameter' можно дублировать.

Пример использования (только для демонстрации синтаксиса):

function Test-Site{
   [CmdletBinding()]
   param(
      [Parameter(Проверка1,Проверка2)]
      [Parameter(Проверка3=$true)]
      $dest1,

      [Parameter(Проверка1,Проверка4)]
      $dest2
   )
   ping $dest2
}

Так как я сам легко путаюсь в понятии параметр, аргумент и атрибут, ниже скриншот с небольшим объяснением:

  • Все что помещается в квадратные скобки - это атрибуты. На скриншоте, под номерами 1 и 2, выделена их часть;
  • Параметры это то, что мы передаем в функцию/команду. Я, например, их часто называю ключами. На скриншоте они находятся под номерами 3 и 4;
  • Внутри атрибутов находятся аргументы. Это просто характеристики параметра. Часть из них выделена под номером 5. Аргументами так же называют значения, которые передаются в параметр.

Разница аргументов и параметров Powershell

Переменная $PSBoundParameters

После того, как у функции появляются параметры, переменная "$args" становится пустой. Вместо нее создается переменная $PSBoundParameters. Переменная хранит хэш-таблицу с ключами-значениями:

function Test-Variables($aa){
   echo "Переменная args: " $args
   echo "Хэш-таблица: " $PSBoundParameters
}
Test-Variables -aa "Test"

Использование PSBoundParameters в Powershell

Использование param в файлах

Эта статья рассматривает использования 'param()' в функциях т.к. это наиболее популярный способ использования. Тем не менее вы можете поместить этот блок в файл:

param(
    $dest1,
    $dest2
)
ping $dest2

Далее мы можем вызвать этот файл и передать в него значения:

.\SomeScript.ps1 -dest1 'google.com' -dest2 'anothersite'

Использование param внутри файла Powershell

Если до блока 'param()' будет какой-то код (кроме комментариев), произойдет ошибка:

  • param : Имя "param" не распознано как имя командлета, функции, файла сценария или выполняемой программы;
  • The term 'Param' is not recognized as the name of a cmdlet

 

Обязательные Mandatory аргументы

Работая с другими командами Powershell вы замечали, что какие-то параметры являются обязательными к заполнению, а какие-то нет. По умолчанию все параметры опциональны. Что бы сделать их обязательными к заполнению используется аргумент 'Mandatory'. Обязательность использования параметра указывается в 'Parameter()':

function Test-Site{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory)]
      $dest1,
      # у параметра dest2 нет проверок
      $dest2
   )
   ping $dest2
}

Обязательные аргументы при использовании параметров в Powershell

Если вы не используете параметр явно, то он у вас будет запрошен. Это правило, в случае выше, касается только одного параметра так как он является обязательным.

Обратите внимание, что объявление 'Mandatory' не снимает с вас обязанности проверки на корректность переданных данных. Это дает лишь возможность остановить работу функции еще на первоначальном этапе.

 

 

Проверка типов и значение по умолчанию

Хороший прием по предотвращению ошибок - добавить проверку типов данных в начале функции. В Powershell много разных типов данных - далее перечислены основные:

  • [string] - строка;
  • [int] - число;
  • [bool] - True/False;
  • [float] - число с плавающей точкой;
  • [DateTime] - дата и время;
  • [array] - массив;
  • [hashtable] - массив ключ-значение;
  • [PSCustomObject] - массив ключ-значение.

Эта проверка выполняется до объявления переменной. 

function Check-Type{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory)]
      [string]$Data
   )
   $Data
   $Data.GetType()
}
Check-Type -Data 1
Check-Type -Data $True

Присваивание типов данных в параметре Powershell

Обратите внимание, что в функцию передается булево значение и число. Так как они могут быть преобразованы в строки - эта конвертация происходит. В случае массивов произошла бы ошибка т.к. он не может быть преобразован в строку.

У некоторых типов вы можете добавить скобки '[]'. Такой прием говорит, что вы ожидаете получить массив определенных типов. В случае строк '[string]' массив строк будет выглядеть '[string[]]' (ниже пример на числах):

function Check-Type{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory)]
      [int[]]$Data
   )
   $Data
   $Data.GetType()
}
Check-Type -Data '12'

Создание коллекции (массива) в функции Powershell

Объявить значение по умолчанию мы можем только у аргумента, который не является 'Mandatory'. Это делается следующим образом:

function Test-Site{
   [CmdletBinding()]
   param(
      [string]$dest1=1
   )
   $dest1
   $dest1.GetType()
}
Test-Site

Присваивание значения по умолчанию в параметре Powershell

switch

Аналогичным образом мы можем объявить переменную типа switch. Если параметр будет указан, то такая переменна будет иметь значение 'True':

function Do-Stuff{
   [CmdletBinding()]
   param(
      [switch]$var
   )
   Write-Host "Параметр указан: $($var.IsPresent)"
}

Пример работы switch в параметре функции Powershell

Такой подход уменьшает риск ошибок и сокращает время на написание команды. Использование switch похоже на bool, но у них есть разница. В случае '[bool]' нужно будет указывать значение параметра.

 

Разделение параметров на группы с ParameterSetName

В ситуациях, когда в функцию нужно передать разный набор обязательных параметров, мы можем использовать атрибут ParameterSetName. Для примера можно посмотреть на описание синтаксиса команды 'Get-EventLog':

Get-Command Get-EventLog -Syntax

Группировка параметров Powershell

У нас выводится 2 возможных варианта использования команды. Для каждого из варианта использования команды могут быть определены свои индивидуальные ключи. Именно для этого используется ParameterSetName.

Создадим команду с 2-умя группами. Первая группа 'Group1' работает с именами пользователей, а 'Group2' только с идентификаторами и требует дополнительно параметра:

function Get-MessageInfo{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory, ParameterSetName='Group1')]
      $User,
      [Parameter(Mandatory, ParameterSetName='Group2')]
      $ID,
      [Parameter(Mandatory, ParameterSetName='Group2')]
      $Message
   )
   if ($ID){
      return "Выбрана 2-оя группа с ID $ID и Message $Message"
   }
   return "Выбрана 1-ая группа с User $User"
}
Get-MessageInfo -User "Alex"
Get-MessageInfo -ID 123

Разделение параметров на группы с ParameterSetName Powershell

На скриншоте видно, что если мы введем 'ID', то появится диалог с вводом 'Message'. Вы так же можете попробовать использовать кнопку 'tab' после выбора одной из групп - параметры из другой группы перестанут предлагаться.

Если вы попробуете запустить команду без указания каких либо групп - получите ошибку:

Вызов параметров из разных групп Powershell

  • Не удается разрешить набор параметров с использованием указанных именованных параметров.
  • parameter set cannot be resolved using the specified named parameters

Группу, которую вы планируете использовать по умолчанию, можно определить в 'CmdletBinding' используя атрибут 'DefaultParameterSetName':

[CmdletBinding(DefaultParameterSetName='Group1')]

Указание группы параметров по умолчанию с DefaultParameterSetName в Powershell

Один ключ может находится в нескольких группах. Для этого, группу, нужно указать в разных 'Parameter()'. Каждый аргумент, указанный в Parameter, будет действовать для определенной группы. Так, в случае ниже, в одной группе "$Message" является обязательным, а в другой опциональным параметром:

function Get-MessageInfo{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory, ParameterSetName='Group1')]
      $User,
      [Parameter(Mandatory, ParameterSetName='Group2')]
      $ID,
      [Parameter(Mandatory, ParameterSetName='Group1')]
      [Parameter(ParameterSetName='Group2')]
      $Message
   )
   if ($ID){
      return "Message не используется"
   }
   return "Указан $Message"
}
Get-MessageInfo -ID 123
Get-MessageInfo -User "Alex"

Размещение параметров в разные группы Powershell

Определение выбранной группы с $PSCmdlet

После вызова команды создается переменная $PSCmdlet. В этой переменной хранятся разные свойства команды. Одно из таких свойств 'ParameterSetName', который показывает выбранную группу. Это может понадобиться что бы более удобно расписать логику:

function Get-Sum{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory, ParameterSetName='Group1')]
      $a,
      [Parameter(Mandatory, ParameterSetName='Group1')]
      [Parameter(Mandatory, ParameterSetName='Group2')]
      $b,
      [Parameter(Mandatory, ParameterSetName='Group2')]
      $c
   )
   $group = $PSCmdlet.ParameterSetName
   Write-Host "Выбрана группа $group"
   # в зависимости от группы
   # разные действия
   if ($group -eq 'Group1'){
        return $a + $b + 5
   }
   else{
        return $с + $b + 10
   }
}

Привязка ключей к разным группам Powershell

Если какой-то параметр не будет принадлежать к конкретной группе - его можно будет использовать в любых комбинациях.

 

Позиционные параметры с Position

При создании команды каждый параметр имеет свою позицию. Эти позиции соответствуют порядку их объявления внутри функции:

function Get-Sum{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory)]
      $a,
      [Parameter(Mandatory)]
      $b,
      [Parameter(Mandatory)]
      $c
   )
   return $a + $b + $c
   
}

Использование позиций в параметрах функции Powershell

Так как позиционное использование параметров может привести к проблемам - вы можете запретить их не использование в 'CmdLetBindint':

[CmdletBinding(PositionalBinding=$false)]

'PositionalBinding' запрещает неявное использование параметров - это когда вы не объявляли их сами. С помощью аргумента 'Postion' вы можете объявить их явно:

function Get-Sum{
   [CmdletBinding(PositionalBinding=$false)]
   param(
      [Parameter(Mandatory, Position=0)]
      $a,
      [Parameter(Mandatory)]
      $b,
      [Parameter(Mandatory, Position=1)]
      $c
   )
   return $a + $b + $c
}
Get-Sum 1 2 -b 3

Запрет на использования позиционных параметров Powershell

Такой подход часто используется в обычных командах Powershell. Параметры типа 'Name' или 'ComputerName' могут работать позиционно, а остальные нет.

 

Параметры конвейера

Для использования конвейера можно определить несколько аргументов:

  • ValueFromPipeline - работает с массивами. Может быть использован в функции единожды;
  • ValueFromPipelineByPropertyName - принимает массивы ключ значение. Можно использовать множество раз.

Создадим функцию, которая будет принимать оба параметра:

function Get-Data{
   [CmdletBinding()]
   param(
      [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]
      [string]$Message
   )
   process {
      $Message
   }
}
@(1,2,3) | Get-Data
[PSCustomObject]@{Message='Hello there';} | Get-Data

Привязка конвейера к параметру Powershell

В отличие от всех предыдущих примеров, при создании конвейера, мы должны использовать блок Process. Это единственный блок, функционал которого будет повторяться для каждого элемента переданного через конвейер. Если вы его не будете использовать - функция будет выполнена только для последнего элемента. Более подробно конвейер обсуждался в предыдущей статье: "Разбираем работу конвейера Powershell на примере команд и создании функции".

Единственный момент, который не оговорен в той статье, 'ValueFromPipeline' можно использовать несколько раз, но в определенном случае. Если у вы используете группировку (разделяете параметры на группы) и указываете один из параметров явно:

function Get-Salary{
   [CmdletBinding(DefaultParameterSetName='Group1')]
   param(
      [Parameter(Mandatory, ParameterSetName='Group1', ValueFromPipeline)]
      $User,
      [Parameter(Mandatory, ParameterSetName='Group2', ValueFromPipelineByPropertyName)]
      $ID,
      [Parameter(Mandatory, ParameterSetName='Group2', ValueFromPipeline)]
      $Message
   )
   process {
      if ($ID){
         return "Выбрана 2-оя группа с ID $ID и Message $Message"
      }
      return "Выбрана 1-ая группа с User $User"
   }
}
# Явно указали параметр ID
# значит используем 2-ую группу
@(1,2,3) | Get-Salary -ID 1

# Используем группу по умолчанию
@(1,2,3) | Get-Salary

Использования нескольких параметров ValueFromPipeline в Powershell

 

Включаем значения вне параметров с ValueFromRemainingArguments

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

Атрибут 'ValueFromRemainingArguments' объявляется следующим образом:

function Get-Data{
   [CmdletBinding()]
   param(
      $SomeMessage,
      [Parameter(Position=1, ValueFromRemainingArguments)]
      $Others
   )
   Write-Host "Эти значения не привязаны к параметрам $Others"
}
Get-Data -SomeMessage 1 2 3 4 5

Использование ValueFromRemainingArguments в Powershell

Обратите внимание, что порядок в этом случае не важен.

 

Атрибуты валидации параметров

Значения у параметров могут проходить разные проверки. Для этих проверок существуют разные атрибуты:

  • [AllowNull()]  - позволяет использовать $null у параметров с другим типом данных. Если вы объявляете, например, тип параметра '[array]', а передаете $null, произойдет ошибка. Этот параметр помогает ее избежать у 'Mandatory';
  • [AllowEmptyString()] - то же самое, что и 'AllowNull', но если у вас указан параметр типа '[string]';
  • [AllowEmptyCollection()] - аналогичен предыдущем двум, но для коллекций, например [string[]];
  • [ValidateNotNull()] - проверяет что не передан $null. Нужен для не 'Mandatory' параметров;
  • [ValidateNotNullOrEmpty()] - проверяет, что в параметр не равен $null и пустой строке. Так же используется не для '[Mandatory]' параметров;
  • [ValidateCount(1,5)] - минимальное и максимальное количество значений переданных через параметр;
  • [ValidateLength(1,10)] - минимальная и максимальная длина в параметре. В том числе можно использовать аргументы: 'Positivem', 'Negative', 'NonPositive' (0 или меньше), 'NonNegative' (0 или больше);
  • [ValidateRange(0,10)] - проверка на минимальное и максимальное значения числа;
  • [ValidatePattern("[0-9][0-9][0-9][0-9]")] - проверка по шаблону регулярных выражений;
  • [SupportsWildcards()] - проверка на простые регулярные выражения в виде "*","?","[]" и т.д.;
  • [ValidateScript({$_ -ge (get-date)})] - проверка через дополнительный скрипт;
  • [ValidateSet("Low", "Average", "High")] - ограничение выбора значений;
  • [ValidateDrive('C','D')] - проверка, что значение является путем и относится к диску 'C' или 'D';
  • [ValidateUserDrive] - проверяет, что путь начинается с 'User:\'. Используется в JEA;
  • DynamicParam {<statement-list>} - динамические параметры, которые работают в зависимости от условий. Например функция может возвращать публичную и приватную информацию. Если запрошена приватная информация - дополнительно нужно ввести пароль (появиться дополнительный параметр).

Рассмотрим некоторые из этих атрибутов.

Проверка на $null

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

Function Get-SomeInfo {
    Param(
        [Parameter(Mandatory)]
        [array]$Data
    )
    $Data
}
Get-SomeInfo -Data $null

Передача NULL в параметр Powershell

Ошибки при этом могут быть разными:

  • Не удается привязать аргумент к параметру "Data", так как он имеет значение NULL
  • Не удается привязать аргумент к параметру "A1", так как он представляет собой пустую строку. Cannot bind argument to parameter 'name' because it is an empty.
  • Не удается преобразовать значение "" в тип "System.Boolean". Логические параметры поддерживают только логические значения и числа
  • Не удается привязать аргумент к параметру "A1", так как он имеет значение NULL.

Если в вашей функции это ожидаемый результат - вы можете допустить передачу "$null" с "[AllowNull()]":

Function Get-SomeInfo {
    Param(
        [Parameter(Mandatory)]
        [AllowNull()]
        [array]$Data
    )
    $Data
}
Get-SomeInfo -Data $null

Разрешаем использовать NULL с AllowNull в Powershell

'AllowNull()' работает для типов '[array]' и других типов данных, кроме строк и коллекций. Для них нужно использовать '[AllowEmptyString()]' и '[AllowEmptyCollection()]'.

Перед указанием таких атрибутов стоит проверить во что будет преобразован ваш тип данных, например:

# преобразуется в 0
[int]$null
# в False
[bool]$null
# в False
[switch]$null
# в $null
[PSCustomObject]$null
# в пустую строку
[string]$null

Преобразование $null в Powershell в другой тип данных

У параметров, которые не помечены 'Mandatory', возникнет противоположная проблема. Они пропускают $null без ошибок:

Function Foo {
    Param(
        [array]$A1
    )
    Write-Host $A1
}
Foo -A1 $Null

Запрет на использования Null в Powershell

Что бы остановить выполнение скрипта при $null мы можем пометить параметр как '[ValidateNotNullOrEmpty]' или '[ValidateNotNullOrEmpty()] ':

Function Foo {
    Param(
        [ValidateNotNull()]
        [array]$A1
    )
    Write-Host $A1
}
Foo -A1 $Null

Запрет на использования Null в Powershell

Подсчет значений

Вы можете считать количество элементов в массиве (ValidateCount), длину строк (ValidateLength) и числа (ValidateRange). Эти атрибуты работают одинаково - вам нужно указать минимальное и максимальное значение:

Function Bar {
    Param(
        [ValidateCount(0,5)]
        $A1
    )
    "pass"
}
Bar -A1 @{'Foo1'=$null; 'Foo2'=$null; 'Foo3'=$null; 'Foo4'=$null; 'Foo5'=$null;}
Bar -A1 @(1,2,3,4,5)
Bar -A1 @(1,2,3,4,5,6)

Ограничение на передаваемые значения с ValidateCount Powershell

Проверка по скрипту

Вы можете создать свою проверку параметров с помощью "ValidateScript". Так вы создадите параметр, который запретит указывать прошедшие даты:

Function Bar {
    Param(
        [ValidateScript({$PSItem -ge $(Get-Date)})]
        [datetime]$A1
    )
    $A1
}
Bar -A1 $(Get-Date)
Bar -A1 $(Get-Date).AddSeconds(1)

Проверка параметра через скрипт в Powershell

Ошибка происходит из-за того, что команда отправляет данные, допустим в 11.1 секунд, а валидация в 11.2. Во втором примере мы добавляем 1 секунду что бы ошибки не было.

Вместо "$PSItem" можно использовать "$_".

Проверка по шаблонам регулярных выражений

Мы можем привязать к параметру проверку на простые регулярные выражения (SupportsWildcards) и расширенные (ValidatePattern). Так мы убедимся, что в параметр передают валидный IP адрес:

Function Check-IP {
    Param(
        [ValidatePattern("\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b")]
        [string]$IP
    )
    'pass'
}
Check-IP -IP '127.0.0.1'
Check-IP -IP '256.0.0.1'

Использование шаблона регулярных выражений в параметре Powershell

Ограничение выбора значений с ValidateSet

В некоторых командах есть возможность выбора значений у параметров. Такой выбор осуществляется через кнопку 'tab'. Вы можете проверить это нажав 'tab' в следующей команде:

Test-NetConnection -ErrorAction 

Автозаполнение команд Powershell

У вас будет выполняться переключение между значениями: Continue, Ignore, Inquire и т.д.

Подобный выбор задается в атрибуте ValidateSet:

function Get-Salary{
   [CmdletBinding()]
   param(
      [Parameter(Mandatory)]
      [ValidateSet('Саши', 'Маши')]
      $User
   )
   return "Пароль $user 123"
}

Автозаполнение команд c ValidateSet Powershell

Если вы укажете значение не прописанное в 'ValidateSet', то получите ошибку:

  • Get-Salary : Не удается проверить аргумент для параметра "User". Аргумент "Маши1"

 

Передача ключей и значений в одной переменной (Splatting)

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

Get-Date -Year 2021 -Day 10 -Month 8

Использование ключей в Powershell

Мы можем взять все ключи и значения из этой команды, поместить в hashtable и передать в команду как набор параметров:

$date = @{
  'Year'='2021';
  'Day'='10';
  'Month'='8';
}

Что бы Powershell понял, что мы передаем не одну переменную, а набор ключей и значений, мы должны ее пометить знаком '@':

Get-Date @date

Передача параметров как переменную в Powershell

Такой подход называется 'Splatting' (брызги) и немного повышает читаемость кода. 

Если в hashtable будет находиться дополнительный параметр, который не реализован в команде, то выйдет ошибка:

  • Не удается найти параметр, соответствующий имени параметра
  • A parameter cannot be found that matches parameter name

Обычные массивы так тоже можно передавать, но вы должны знать позиции под которыми должны располагаться значения:

function Test-Funct{
   param(
      [Parameter(Position=0)]
      $pos1,
      [Parameter(Position=1)]
      $pos2,
      [Parameter(Position=2)]
      $pos3
   )
   Write-Host "Позиция $pos1"
   Write-Host "Позиция $pos2"
   Write-Host "Позиция $pos3"
}

$positions = @(1;2;3)
Test-Funct @positions

Передача параметров как массив в Powershell

Используя splatting, в Powershell 7+,  вы можете перезаписывать значения из метода splatting:

$message = @{
  'Object'='Hello world';
  'BackgroundColor'='Blue';
}
$new_message = 'New message'
Write-Host @message -Object $new_message

Передача параметров как массив в Powershell

 

 

Алиасы

К параметрам можно привязать алиасы (короткие имена/псевдонимы). Это делается через атрибут 'Alias()'. Ограничений в количестве атрибутов нет:

function Get-PCName{
    Param(
        [Parameter(Mandatory=$true)]
        [Alias('Computer','PC','IP','Address')]
        $Name
    )
    $Name
}
Get-PCName -Computer 'SRV1'
Get-PCName -PC 'SRV1'
Get-PCName -IP 'SRV1'
Get-PCName -Address 'SRV1'

Создание параметра-алиаса в Powershell 

...

Теги: #powershell


Каналы
Telegram FixMyPc Telegram Лента FixMyPC RSS Rss
Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, преобретенного опыта и лучшие практики в системном администрировании и программировании.