Часто создаваемый вами сценарий или функция принимает какие-то входные данные. Это может быть имя компьютера, путь к файлу и т. п. Можно заставить Windows PowerShell ожидать эти параметры, принимать их из командной строки и размещать их значения в переменных в сценарии или функции. Это делает ввод данных простым и эффективным.
Нужно просто знать, как декларировать свои параметры. Простейший способ выполнения этой задачи — указание блока param:
Param(
[string]$computerName,
[string]$filePath
)
Необязательно разбивать его на отдельные строки, как сделал это я, — вполне легитимно размещать все в одну строку. Но я предпочитаю разбивать на отдельные строки — так проще читать. Если такой блок присутствует в сценарии или функции, Windows PowerShell считывает его и даже разделяет знаками табуляции при вызове сценария или функции. Я аккуратно указал имена параметров: –computerName и –filePath. Они похожи на те, что используются в командлетах Windows PowerShell для подобной информации. Таким образом, мои параметры совместимы с тем, что уже используется в оболочке.
Если я размещу этот код в сценарии по имени Get-Something.ps1, использовать параметры нужно будет примерно так:
./Get-Something –computerName SERVER1 –filePath C:\Whatever
Я могу также сократить имена параметров. Это позволяет мне печатать меньше символов, а результат будет таким же:
./Get-Something –comp SERVER1 –file C:\Whatever
Я могу вообще опустить имена. Windows PowerShell автоматически примет значения, различая их по позиции в строке. При этом мне нужно указать значения параметров в том же порядке, в котором параметры перечислены в моем файле:
./Get-Something SERVER1 C:\Whatever
Ясно, что при использовании имен параметров команду становится проще понять стороннему пользователю. При этом у меня появляется возможность указывать параметры в том порядке, который меня больше устраивает:
./Get-Something –filePath C:\Whatever –computerName SERVER1
Windows PowerShell также предоставляет более сложный способ декларирования параметров. Этот более полный синтаксис позволяет задавать параметры как обязательные, указывать позицию (если этого не сделать, задать параметр можно будет только по его имени) и делать многое другое. Также такой расширенный синтаксис разрешен как в сценариях, так и в функциях:
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$computerName,
[Parameter(Mandatory=$True)]
[string]$filePath
)
И на этот раз все это можно разместить в одной строке, но разбиение позволяет облегчить чтение. Я оформил свои параметры с помощью синтаксиса [Parameter()] и определил их как обязательные.
Если при выполнении моего сценария забыть указать один или оба параметра, оболочка автоматически напомнит о недостающей информации. С моей стороны мне не нужно больше ничего делать для этого. Я также указал, что –computerName находится на первой позиции, а –filePath надо указывать по имени.
У использования директивы [CmdletBinding()] есть ряд других преимуществ. Для начала, она гарантирует, что у моего сценария или функции будут все стандартные параметры, в том числе –Verbose и –Debug. Теперь я могу использовать в своем сценарии или функции Write-Verbose и Write-Debug, а результат работы этих командлетов будет автоматически устранен.
Выполните сценарий или функцию с параметром –Verbose или –Debug, и будет магическим образом автоматически активизирован Write-Verbose или Write-Debug (соответственно). Это отличный способ предоставления пошаговой информации о ходе процесса (Write-Verbose) или отладке сценариев (Write-Debug).
В настоящем виде они принимают только одно значение. Если объявить их как [string[]], они смогут принимать целые коллекции значений. Перечислять значения можно в цикле Foreach, работая в каждый момент времени только с одним значением.
Еще один классный тип параметров — [switch]:
Param([switch]$DoSomething)
Теперь я могу выполнять свой сценарий или функцию без параметра –DoSomething, а внутри кода переменной $DoSomething будет присваиваться значение $False. Если я выполню сценарий с параметром –DoSomething, переменной $DoSomething присвоится значение $True. Нет нужды передавать значение параметра. Windows PowerShell присваивает ему значение $True, если параметр просто присутствует в вызове. Так работают параметры-переключатели switch, такие как параметр –recurse в командлете Get-ChildItem.
Помните, что каждый параметр является собственной сущностью и отделен от следующего параметра запятой. Это видно в следующем коде:
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$computerName,
[Parameter(Mandatory=$True)]
[string]$filePath
)
Весь параметр –computerName, включая его декоратор [Parameter()], размещается до запятой. Запятая означает, что я закончил объявление первого параметра и готов перейти к следующему. Все относящееся к параметру –filePath размещено после запятой. Если мне нужен третий параметр, я добавлю еще одну запятую:
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$computerName,
[Parameter(Mandatory=$True)]
[string]$filePath,
[switch]$DoSomething
)
Все это располагается в блоке Param(). Заметьте, что совершенно не обязательно использовать декоратор [Parameter()] в каждом параметре. Он нужен, когда требуется объявить что-то — обязательность параметра, способность принять входные данные из конвейера, размещение в определенной позиции и т. п. Чтобы узнать подробнее о том, какие другие атрибуты можно таким способом объявлять, выполните в Windows PowerShell команду help about_functions_advanced_parameters.
Рекомендуется писать функции и сценарии так, чтобы они принимали входные данные только через параметры. Это делает их более самодостаточными и простыми для документирования, а также лучше вписывающимися в общую схему работы всей оболочки Windows PowerShell.