Все команды PowerShell могут иметь один или несколько параметров, иногда их называют аргументами. Если вы не используете параметры PowerShell в своих функциях PowerShell, вы не пишете хороший код на PowerShell!
В этой статье вы узнаете практически обо всех аспектах создания и использования параметров или аргументов в PowerShell!
Это пример из моей книги “PowerShell для системных администраторов”. Если вы хотите выучить PowerShell или узнать несколько хитростей профессии, проверьте это!
Зачем вам нужен параметр?
Когда вы начинаете создавать функции, у вас есть возможность включить параметры или нет, и определить, как эти параметры будут работать.
Допустим, у вас есть функция, которая устанавливает Microsoft Office. Возможно, она вызывает установщик Office бесшумно внутри функции. Что делает функция, не имеет значения для наших целей. Базовая функция выглядит так с именем функции и блоком сценария.
В этом примере вы просто запустили Install-Office
без параметров, и он делает свою работу.
Не имеет значения, были ли у функции Install-Office
параметры или нет. По-видимому, у нее не было обязательных параметров; в противном случае PowerShell не позволил бы нам запустить ее без использования параметра.
Когда использовать параметр PowerShell
В Office существует множество различных версий. Возможно, вам нужно установить Office 2013 и 2016. В настоящее время у вас нет способа указать это. Вы могли бы изменять код функции каждый раз, когда хотите изменить поведение.
Например, вы могли бы создать две отдельные функции для установки разных версий.
Это работает, но это не масштабируемо. Это заставляет вас создавать отдельную функцию для каждой версии Office, которая выходит. Вам придется дублировать много кода, когда это не нужно.
Вместо этого вам нужен способ передавать разные значения во время выполнения, чтобы изменить поведение функции. Как это сделать?
Да! Параметры или то, что некоторые люди называют аргументами.
Поскольку мы хотели бы устанавливать разные версии Office без изменения кода каждый раз, вы должны добавить по крайней мере один параметр к этой функции.
Прежде чем быстро придумать параметр PowerShell для использования, важно сначала задать себе вопрос; “Какое минимальное изменение или изменения, по вашему мнению, потребуются в этой функции?”.
Помните, что вам нужно будет перезапустить эту функцию без изменения какого-либо кода внутри функции. В этом примере параметр, вероятно, очевиден для вас; вам нужно добавить параметр Version
. Но, когда у вас есть функция с десятками строк кода, ответ может быть не так очевиден. Пока вы отвечаете на этот вопрос как можно точнее, это всегда поможет.
Итак, вы знаете, что вам нужен параметр Version
. Что теперь? Теперь вы можете добавить его, но, как и в любом отличном языке программирования, существует несколько способов решить эту задачу.
В этом уроке я покажу вам “лучший” способ создания параметров на основе моего почти десятилетнего опыта работы с PowerShell. Однако помните, что это не единственный способ создания параметра.
Существуют также позиционные параметры. Они позволяют передавать значения параметрам, не указывая имя параметра. Позиционные параметры работают, но не считаются “лучшей практикой”. Почему? Потому что их труднее читать, особенно если у вас определено много параметров для функции.
Создание простого параметра PowerShell
Создание параметра для функции требует двух основных компонентов: блока param и самого параметра. Блок param определяется ключевым словом param
, за которым следует набор круглых скобок.
На этом этапе реальная функциональность функции не изменилась ни на йоту. Мы просто подготовили некоторую инфраструктуру, готовясь к созданию первого параметра.
Как только у нас есть блок param, вы создадите параметр. Метод, который я предлагаю вам для создания параметра, включает блок Parameter
, за которым следует тип параметра, за которым следует переменная параметра ниже.
Теперь у нас есть созданный параметр функции в PowerShell, но что произошло здесь на самом деле?
Блок Parameter
является необязательной, но рекомендуемой частью каждого параметра. Как и блок param, это “сантехника функции”, которая готовит параметр к добавлению дополнительной функциональности. Вторая строка – это то место, где вы определяете тип параметра.
В данном случае мы решили привести параметр Version
к строковому типу. Определение явного типа означает, что любое значение, переданное этому параметру, всегда будет пытаться быть “преобразованным” в строку, если оно еще не является таковым.
Тип не обязателен, но настоятельно рекомендуется. Явное определение типа параметра значительно снизит возможность нежелательных ситуаций в будущем. Поверьте мне.
Теперь, когда вы определили параметр, вы можете выполнить команду Install-Office
с передачей строки версии параметру Version
, например, как 2013. Значение, переданное параметру Version
, иногда называется аргументами или значениями параметров.
Что здесь происходит вообще? Вы сказали, что хотите установить версию 2013, но он все равно сообщает вам, что установлена версия 2016. Когда вы добавляете параметр, необходимо помнить также изменить код функции на переменную. Когда параметр передается функции, эта переменная будет раскрыта в то значение, которое было передано.
Измените статический текст 2016 и замените его переменной параметра Version
, преобразовав одинарные кавычки в двойные, чтобы переменная раскрывалась.
Теперь вы можете видеть, что любое значение, переданное параметру Version
, затем будет передано в функцию как переменная $Version
.
Атрибут обязательного параметра
Вспомните, что я упоминал о строке [Parameter()]
, как о “системной сантехнике” и необходимости подготовить функцию для дальнейшей работы? Добавление атрибутов параметра к параметру – это тот дополнительный этап, о котором я ранее говорил.
A parameter doesn’t have to be a placeholder for a variable. PowerShell has a concept called parameter attributes and parameter validation. Parameter attributes change the behavior of the parameter in a lot of different ways.
Например, одним из наиболее распространенных атрибутов параметра, который вы установите, является ключевое слово Mandatory
. По умолчанию вы могли бы вызывать функцию Install-Office
без использования параметра Version
, и она выполнялась бы нормально. Параметр Version был бы необязательным. Конечно, он не расширил бы переменную $Version внутри функции из-за отсутствия значения, но функция всё равно бы выполнилась.
Часто при создании параметра вы захотите, чтобы пользователь всегда использовал этот параметр. Вы будете зависеть от значения параметра где-то в коде функции, и если параметр не передан, функция завершится ошибкой. В таких случаях вы хотите, чтобы пользователь обязательно передавал значение этому параметру в вашу функцию. Вы хотите, чтобы этот параметр стал обязательным.
Заставить пользователей использовать параметр просто, когда у вас уже есть основная структура, построенная так, как здесь. Вам нужно включить ключевое слово Mandatory
в скобки параметра. После того как вы это сделаете, выполнение функции без параметра приостановит выполнение до тех пор, пока не будет введено значение.
Функция будет ждать, пока вы укажете значение для параметра Version
. После этого, нажав Enter, PowerShell выполнит функцию и продолжит выполнение. Если вы предоставите значение для параметра, PowerShell не будет запрашивать его каждый раз.
Атрибуты проверки параметров в PowerShell
Сделать параметр обязательным – один из наиболее распространенных атрибутов параметров, которые можно добавить, но также можно использовать атрибуты проверки параметров. В программировании всегда важно ограничивать ввод пользователя как можно тщательнее. Ограничение информации, которую пользователи (или даже вы сами!) могут передавать вашим функциям или скриптам, позволит избежать лишнего кода внутри вашей функции, который должен учитывать все возможные ситуации.
Изучение на примерах
Например, в функции Install-Office
я продемонстрировал передачу значения 2013
, потому что знал, что это сработает. Я написал этот код! Я предполагаю (никогда не делайте этого в коде!) что очевидно, что любой, кто что-то знает, укажет версию либо 2013, либо 2016. Ну, что очевидно для вас, может быть не так очевидно для других людей.
Если хотите быть техничным относительно версий, наверное, было бы более точно указать версию 2013 как 15.0
, а 2016 как 16.0
, если бы Microsoft все еще использовала схему версионирования, которую они использовали ранее. Но что, если, предполагая, что они укажут версию 2013 или 2016, в вашем коде внутри функции будет что-то, что ищет папки с этими версиями или что-то еще?
Ниже приведен пример, где вы можете использовать строку $Version
в пути к файлу. Если кто-то передает значение, которое не завершает имя папки Office2013
или Office2016
, это приведет к ошибке или, что еще хуже, удалению непредвиденных папок или изменению вещей, которые вы не учли.
Чтобы ограничить пользователя вводом ожидаемых значений, вы можете добавить некоторую валидацию параметров PowerShell.
Используйте атрибут валидации параметров ValidateSet
Существует несколько видов валидации параметров, которые вы можете использовать. Для полного списка выполните Get-Help about_Functions_Advanced_Parameters
. В этом примере, атрибут ValidateSet
вероятно будет наилучшим выбором.
Атрибут валидации ValidateSet
позволяет указать список значений, разрешенных в качестве значения параметра. Поскольку мы учитываем только строки 2013 или 2016, я хочу убедиться, что пользователь может указывать только эти значения. В противном случае функция сразу завершится с уведомлением о причине.
Вы можете добавить атрибуты валидации параметров прямо под ключевым словом Parameter
. В этом примере в скобках атрибута параметра у вас есть массив элементов; 2013 и 2016. Атрибут валидации параметра сообщает PowerShell, что допустимыми значениями для Version
являются только 2013 или 2016. Если вы попытаетесь передать что-то, кроме того, что есть в наборе, вы получите ошибку с уведомлением о том, что у вас есть только определенное количество вариантов.
Атрибут ValidateSet
– общий атрибут валидации. Для полного разбора всех способов ограничения значений параметров ознакомьтесь с темой справки Functions_Advanced_Parameters
, запустив Get-Help about_Functions_Advanced_Parameters
.
Наборы параметров
Предположим, вы хотите, чтобы некоторые параметры PowerShell использовались только с другими параметрами. Возможно, вы добавили параметр Path
к функции Install-Office
. Этот путь установит любую версию установщика. В этом случае вы не хотите, чтобы пользователь использовал параметр Version
.
Вам нужны наборы параметров.
Параметры могут быть сгруппированы в наборы, которые могут использоваться только с другими параметрами из того же набора. Используя функцию ниже, теперь можно использовать как параметр Version
, так и параметр Path
, чтобы получить путь к установщику.
Однако это создает проблему, поскольку пользователь может использовать оба параметра. Кроме того, поскольку оба параметра обязательны, им придется использовать оба, когда это не требуется. Чтобы исправить это, мы можем поместить каждый параметр в набор параметров, как показано ниже.
Определив имя набора параметров для каждого параметра, вы можете контролировать группы параметров вместе.
Набор параметров по умолчанию
Что, если пользователь попытается запустить Install-Office
без параметров? Это не предусмотрено, и вы увидите дружественное сообщение об ошибке.

Чтобы исправить это, вам нужно определить набор параметров по умолчанию в области CmdletBinding()
. Это указывает функции выбирать набор параметров для использования, если явно не указаны параметры, изменяя [CmdletBinding()]
на [CmdletBinding(DefaultParameterSetName = 'ByVersion')]
. Теперь, когда вы запускаете Install-Office
, он запросит параметр Version
, поскольку будет использовать этот набор параметров.
Ввод через конвейер
В предыдущих примерах вы создавали функции с параметром PowerShell, который можно передавать только с использованием типичного синтаксиса -ParameterName Value. Но, как вы уже узнали, в PowerShell есть интуитивный конвейер, который позволяет вам без применения “типичного” синтаксиса легко передавать объекты от одной команды к другой.
При использовании конвейера вы “цепляете” команды вместе с символом трубы |
, что позволяет пользователю отправлять вывод команды, например, Get-Service
, к Start-Service
в качестве ярлыка для передачи параметра Name
в Start-Service
.
«Старый» способ с использованием цикла
В вашей пользовательской функции, с которой вы работаете, вы устанавливаете Office и имеете параметр Version
. Допустим, у вас есть список имен компьютеров в файле CSV в одной строке с версией Office, которую нужно установить на них, во второй строке. Файл CSV выглядит примерно так:
Вы хотите установить версию Office, которая находится рядом с каждым компьютером, на этот компьютер.
Во-первых, вам нужно добавить параметр ComputerName
в функцию, чтобы передавать разные имена компьютеров для каждой итерации функции. Ниже приведен псевдокод, представляющий код, который может находиться в вымышленной функции, а также добавлен экземпляр Write-Host
, чтобы увидеть, как расширяются переменные внутри функции.
После добавления параметра ComputerName
в функцию, вы можете сделать это, считав файл CSV и передавая значения для имени компьютера и версии функции Install-Office
.
Создание конвейера ввода для параметров
Этот метод чтения строк CSV и использования цикла для передачи свойств каждой строки в функцию является “старым” способом. В этом разделе вы хотите полностью отказаться от цикла foreach
и вместо этого использовать конвейер.
Как есть, функция вообще не поддерживает конвейер. Было бы логично предположить, что вы можете передать каждое имя компьютера и версию функции с использованием конвейера. Ниже мы читаем CSV и непосредственно передаем его в Install-Office,
, но это не работает.
Вы можете предполагать всё, что угодно, но это не делает его работающим. Нас подсказывают о параметре Version
, когда вы знаете, что Import-Csv
отправляет его как свойство объекта. Почему это не работает? Потому что вы ещё не добавили поддержку конвейера.
В функции PowerShell существует два типа ввода из конвейера; ByValue (весь объект) и ByPropertyName (одно свойство объекта). Какой из них, по вашему мнению, лучший способ объединить вывод Import-Csv
с вводом Install-Office
?
Без какого-либо рефакторинга вы можете использовать метод ByPropertyName
, поскольку, в конце концов, Import-Csv
уже возвращает свойства Version
и ComputerName
, так как они являются столбцами в CSV.
Добавление поддержки конвейера к пользовательской функции гораздо проще, чем вы думаете. Это всего лишь атрибут параметра, представленный одним из двух ключевых слов; ValueFromPipeline
или ValueFromPipelineByPropertyName
.
В этом примере вы хотите привязать свойства ComputerName
и Version
, возвращаемые из Import-Csv
, к параметрам Version
и ComputerName
Install-Office
, поэтому вы будете использовать ValueFromPipelineByPropertyName
.
Поскольку вы хотите привязать оба эти параметра, вы добавите это ключевое слово к обоим параметрам, как показано ниже, и повторно выполните функцию, используя конвейер.
Странно. Он выполнился только для последней строки в CSV. Что происходит? Он просто выполнел функцию для последней строки, потому что вы пропустили концепцию, которая не требуется при создании функций без поддержки конвейера.
Не Забудьте Блок Процесса!
Когда вам нужно создать функцию, которая включает поддержку конвейера, вы должны включить (как минимум) “встроенный” блок внутри вашей функции, называемый. process
. Этот блок процесса сообщает PowerShell, что при получении входных данных из конвейера нужно выполнять функцию для каждой итерации. По умолчанию будет выполнена только последняя.
Технически вы можете добавить другие блоки, такие как begin
и end
, но скриптеры не используют их так часто.
Чтобы указать PowerShell выполнять эту функцию для каждого объекта, поступающего на вход, я добавлю блок process
, который включает в себя код внутри него.
Теперь вы можете видеть, что свойства Version
и ComputerName
каждого объекта, возвращенные из Import-Csv
, были переданы в Install-Office
и привязаны к параметрам Version
и ComputerName
.
Ресурсы
Чтобы погрузиться в детали работы параметров функции, ознакомьтесь с моим постом на блоге о функциях PowerShell.
I also encourage you to check my Pluralsight course entitled Building Advanced PowerShell Functions and Modules for an in-depth breakdown of everything there is to know about PowerShell functions, function parameters, and PowerShell modules.