Заметки о Windows и других программных продуктах Microsoft...

Передача параметров в PowerShell

Передача параметров в PowerShell

Иногда создаваемый вами сценарий или функция должна принять какое либо входное значение  — имя компьютера, путь к папке, название сервиса и т.п. В PowerShell есть несколько способов передать данные в сценарий из командной строки, сделав их ввод более простым и эффективным.

Самый простой вариант передачи данных — использовать встроенную переменную $args, которая имеет тип одномерный массив (hashtable). Для этого создадим скрипт с именем service.ps1 вот такого содержания:

Get-Service -Name $args[0] -ComputerName $args[1]

Этот скрипт должен вывести состояние заданного сервиса\сервисов для одного или нескольких компьютеров. Имя сервиса и компьютера передаются в скрипт в качестве аргументов.

Теперь выполним его, указав в качестве аргументов сервис печати (spooler) и имя компьютера SRV1:

.\service.ps1 spooler SRV1

Получив эту команду, PowerShell подставит вместо $args[0] название сервиса, вместо $args[1] имя компьютера и выведет полученный результат.

использование переменной $args

 

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

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

Param (
[string]$service,
[string]$computer
)

Get-Service -ServiceName $service -ComputerName $computer

Разбивать сценарий на строки необязательно, вполне возможно записать все в одну строку. Если блок param имеется в сценарии или функции, PowerShell сам считывает его и разделяет знаками табуляции. Поскольку имена параметров явно указаны, то их можно вводить в любом порядке, например так:

.\service.ps1 -Service spooler -Computer SRV1

использование параметров

 

Чтобы вводить меньше текста, имена параметров можно сократить, например так:

.\service.ps1 -Serv spooler -Comp SRV1

Имена можно и совсем опустить, хотя это и не очень правильно. В этом случае PowerShell примет значения параметров в том порядке, в каком они указаны в команде. Так же как и при использовании $args, значения надо указывать в том же порядке, в котором они перечислены в сценарии:

.\service.ps1 spooler SRV1

варианты передачи параметров

 

Есть в PowerShell и более сложный способ передачи параметров, позволяющий задавать параметры как обязательные, указывать для каждого позицию и многое другое. Для примера изменим сценарий следующим образом:

[CmdletBinding()]

Param (
[Parameter (Mandatory=$true, Position=1)]
[string]$service,

[Parameter (Mandatory=$true, Position=2)]
[string]$computer
)

Get-Service -ServiceName $service -ComputerName $computer

Здесь оба параметра указаны как обязательные (Mandatory=$true) и для каждого задана своя позиция. Это значит, что оба параметра обязательно должны быть указаны и должны идти строго в определенном порядке. Теперь если не указать один из параметров, то PowerShell автоматически напомнит об этом и предложит ввести недостающую информацию.

обязательные параметры

 

Использование расширенного синтаксиса позволяет задавать различные ограничения для вводимых параметров. Еще раз изменим сценарий, указав в нем для имени компьютера ограничение в 3 символа (ValidateLength(1,3):

CmdletBinding()]

Param (
[Parameter (Mandatory=$true)]
[string]$service,

[Parameter (Mandatory=$true)]
[ValidateLength(1,3)]
[string]$computer
)

Get-Service -ServiceName $service -ComputerName $computer

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

.\service.ps1 -Service spooler -Computer SRV1.contoso.com

А такая отработает нормально:

.\service.ps1 -Service spooler -Computer SRV1

ограничение на длину передаваемого параметра

 

Подобным образом можно задавать практически любые ограничения для входных параметров. Для этого есть возможность использовать регулярные выражения, скрипты и пр. Узнать подробнее об этих возможностях можно, выполнив в PowerShell команду help about_functions_advanced_parameters.

 
 
Комментарии

Добрый день, Кирилл.
Как передать в функцию команду?

cls;
function funk
{
$args[0]
}

$command = @»
1..10 | foreach {
$_;
Write-Host -f Cyan «—»
}
«@

funk $command

Вот и решение 🙂

cls;

# Для типизации параметров стоит использовать
# тип объекта — scriptblock
function funk ([scriptblock]$cmd)
{
# амперсанд — оператор вызова.
&$cmd
}

# Код в фигурных скобках всегда выполняемый
# Как пример может служить оператор for, foreach или if
# Посмотреть объект можно методом .GetType()
$command = {
1..10 | foreach {
$_;
Write-Host -f Cyan «—»
}
}

funk -cmd $command