powershell запросить параметр у пользователя
Запрос на ввод данных Пользователем в PowerShell
Я хочу запросить у пользователя ряд входных данных, включая пароль и имя файла.
есть ли лучший способ получить пользовательский ввод в PowerShell?
4 ответов:
Read-Host это простой вариант для получения строки ввода от пользователя.
чтобы скрыть пароли, вы можете использовать:
чтобы преобразовать пароль в обычный текст:
чтобы получить доступ к информации без вызова метода, оставьте скобки:
$Host.UI.Prompt.OverloadDefinitions даст вам определение(определения) метода. Каждое определение отображается как (
использование привязки параметров, безусловно,путь сюда. Мало того, что это очень быстро писать (просто добавить [Parameter(Mandatory=$true)] выше ваших обязательных параметров), но это также единственный вариант, который вы не будете ненавидеть себя позже.
[Console]::ReadLine явно запрещен FxCop правила для PowerShell. Зачем? Потому что он работает только в PowerShell.exe, а не PowerShell ISE, PowerGUI, так далее.
Read-Host это, попросту говоря, дурной тон. Read-Host бесконтрольно останавливает сценарий для запроса пользователя, что означает, что у вас никогда не может быть другого сценария, который включает сценарий, использующий Read-Host.
вы пытаетесь запросить параметры.
вы должны использовать [Parameter(Mandatory=$true)] атрибут и правильный ввод, чтобы запросить параметры.
поместите это в верхней части вашего сценария. Это приведет к тому, что скрипт запросит у пользователя пароль. Полученный пароль может быть использован в другом месте вашего скрипта через $pw.
Если вы хотите отладить и увидеть значение пароля, который вы только что прочитали, используйте:
в качестве альтернативы, вы можете добавить его в качестве параметра скрипта для ввода как часть выполнения скрипта
Передача параметров в PowerShell
Иногда создаваемый вами сценарий или функция должна принять какое либо входное значение — имя компьютера, путь к папке, название сервиса и т.п. В PowerShell есть несколько способов передать данные в сценарий из командной строки, сделав их ввод более простым и эффективным.
Этот скрипт должен вывести состояние заданного сервиса\сервисов для одного или нескольких компьютеров. Имя сервиса и компьютера передаются в скрипт в качестве аргументов.
Теперь выполним его, указав в качестве аргументов сервис печати (spooler) и имя компьютера SRV1:
.\service.ps1 spooler SRV1
Более эффективным способом передачи параметров является использование в сценарии блока param. Для примера возьмем наш сценарий и изменим его:
Param (
[string]$service,
[string]$computer
)
Разбивать сценарий на строки необязательно, вполне возможно записать все в одну строку. Если блок param имеется в сценарии или функции, PowerShell сам считывает его и разделяет знаками табуляции. Поскольку имена параметров явно указаны, то их можно вводить в любом порядке, например так:
Чтобы вводить меньше текста, имена параметров можно сократить, например так:
.\service.ps1 spooler SRV1
Есть в PowerShell и более сложный способ передачи параметров, позволяющий задавать параметры как обязательные, указывать для каждого позицию и многое другое. Для примера изменим сценарий следующим образом:
Param (
[Parameter (Mandatory=$true, Position=1)]
[string]$service,
[Parameter (Mandatory=$true, Position=2)]
[string]$computer
)
Здесь оба параметра указаны как обязательные (Mandatory=$true) и для каждого задана своя позиция. Это значит, что оба параметра обязательно должны быть указаны и должны идти строго в определенном порядке. Теперь если не указать один из параметров, то PowerShell автоматически напомнит об этом и предложит ввести недостающую информацию.
Использование расширенного синтаксиса позволяет задавать различные ограничения для вводимых параметров. Еще раз изменим сценарий, указав в нем для имени компьютера ограничение в 3 символа (ValidateLength(1,3):
Param (
[Parameter (Mandatory=$true)]
[string]$service,
[Parameter (Mandatory=$true)]
[ValidateLength(1,3)]
[string]$computer
)
И теперь, если введенные значения не подходят под заданные ограничения, то сценарий не отработает. В нашем случае вот такая команда выдаст ошибку
А такая отработает нормально:
Как создавать команды и функции в Powershell вызывать их и передавать параметры
Во время написания программы или скрипта любой начинающий программист столкнется с проблемой где ему нужно повторить код дважды и в этот могут помочь функции в Powershell. Функции так же называют методами и процедурами. Кроме многократного использования они так же полезны для выделения одной части скрипта от другой, хоть она и выполняется один раз. Методы описанные ниже существуют во множестве языках и работают по похожему сценарию.
Навигация по посту
Создание
Представим, что каждое утро вы проверяете 50 последних логов за 14 часов журнала Application с помощью этой команды:
Команда не очень сложная, но в скором времени ее надоест писать. Для сокращения этой работы ее можно выделить в отдельную функцию:
Любая функция обязательно должна состоять из трех вещей:
После написания функции она вызывается по имени:
Учитывая, что нам может потребоваться получить данные не за последние 14 часов и более чем за 50 дней нам может потребуется изменить ее передав параметры.
Именование
Не обязательно использовать имя такого же плана, как принято в Powershell, то есть вместо «Get-DayLog» можно писать «daylog». Такой подход рекомендуем и является распространенной практикой, который поможет отличить запуск сторонней программы от функции.
Функции в Powershell всегда именуются по следующему признаку. Первое слово это глаголы типа:
Удаленное управление через Powershell
Передача параметров
Чаще всего функции принимают какой-то объект и возвращают. Для примера может потребоваться изменить время, когда эти логи созданы и их количество. В существующей функции такой возможности нет. Вы можете править код каждый раз, но это не подход программиста. Что бы такая возможность появилась в функции нужно добавить параметры, которая она будет принимать:
Параметры функции обозначаются в круглые скобки и пишутся после названия функции и до выражения.
Теперь, для вызова функции, требуется передавать два параметра:
Установка значений по умолчанию
Мы должны всегда указывать ключ param2, что добавляет немного работы. Что бы это исправить достаточно поменять их местами:
Как видно на примере, если мы не указываем ключи param1 и param2 важна последовательность, так как именно в такой последовательности они будут присвоены переменным внутри функций.
Возвращение значений
Это будет работать до тех пор, пока мы не решим изменить функцию присвоив переменные:
Так как функции это отдельная часть программы вся логика и ее переменные не должны касаться другой ее части. Область видимости переменных подразумевает это же. Все переменные, созданные внутри функции остаются в ней же. Эту ситуацию можно исправить с помощью return:
Я бы рекомендовал всегда возвращать значения через return, а не использовать вывод используя команды типа Write-Output внутри функции. Использование return останавливает работу функции и возвращает значение, а это значит что его не стоит ставить по середине логики если так не планировалось.
Возвращаемых значений может быть несколько. Для примера создадим функцию, которая будет считать зарплату и налог:
Я вернул оба значения разделив их запятой. По умолчанию всегда возвращается массив. Массивы в Powershell это набор не именованных параметров. Более подробно о них мы уже писали.
В случае с массивами, что бы добавит надпись о зарплате, и налоге нужно использовать индексы:
Возвращаться может любой тип данных. Например мы можем использовать другой тип данных хэш таблицы, которые в отличие от массивов именованные:
Подробно о хэш таблицах в Powershell вы можете почитать в предыдущих статьях. Далее так же будет несколько примеров с ними.
Вы можете возвращать любой тип данных и в любом формате и последовательности. Каждый из них имеет своё преимущество.
Область видимости переменных
Все переменные объявленные до момента вызова функции могут быть ей использованы:
Такой подход не запрещает переопределить переменную внутри функции дав ей другое значение:
Как уже писалось выше, значения внутри функции не доступны вне нее и у нас есть все возможности что бы этого не потребовалось. Тем не менее есть способ объявить внутри функции переменную, которая будет доступна вне нее.
Дополнительные возможности работы с параметрами
Строгие типы данных
Powershell автоматически преобразует типы данных. В отличие от других языков результат этого выражения будет число 3, а не «111»:
Такой подход может привести к ошибке. Мы можем исправить это объявляя типы:
То есть объявляя типы данных мы либо получим ошибку избежав неверного преобразования. Если бы мы передавали такую строку «1», то у нас корректно выполнилось преобразование в число.
Таких типов данных в Powershell всего 13:
Примеры работы с некоторыми типами данных вы увидите далее.
В языках программирования есть понятие позиционного параметра. Это такие параметры, которые могут передаваться без имен:
Обязательные параметры Mandatory
Попробуем выполнить следующий пример, который должен вернуть дату изменения файла:
Представьте что до получения даты изменения файла будут еще какие-то действия, например удаление и создание файлов, которые могут привести к поломке компьютера или программы. Что бы этого избежать можно объявить этот параметр обязательным:
Атрибут Mandatory обязывает указывать значение. Если оно будет проигнорировано, то мы получим ошибку еще до момента выполнения функции.
Param()
Вы могли видеть функции, которые имеют значение Param(). Это значение так же объявляет параметры. На предыдущем примере это значение использовалось бы так:
Microsoft Рекомендует использовать именно такой синтаксис написания функции, но не обязывает его использовать. Такой синтаксис говорит, что это не просто функция, а командлет.
Создадим скрипт, в котором будет происходить умножение, где добавим несколько обязательных параметров используя синтаксис с Param:
Position говорит под каким номером передается значение.
CmdletBinding()
Использование этого атрибута позволяет расширять возможность по созданию командлетов. Microsoft пишет, что использование CmdletBinding или Parameter расширяет возможность функций в Powershell, но по моему опыту не всегда все срабатывает и нужно ставить оба атрибута.
На примере ниже я установил ограничение на длину строк с 1 по 13 символов с помощью ValidateLength(1,13). Position=1 говорит об индексе элемента в массиве:
Таких дополнительных аргументов для команд достаточно много. Для примера еще несколько атрибутов, которые можно добавить в блок parameter:
Отдельные блоки типа [ValidateLength]:
Больше примеров и аргументов на сайте Microsoft.
Использование массивов
Передача массивов в виде параметров
В предыдущих статьях было множество примеров по работе с массивами и хэш таблицами. Их же, как и любой другой тип данных, мы можем передавать в функцию. Для примера все команды Powershell, которые имеют ключ ComputerName, могут выполняться удаленно. Большинство таких команд могут принимать в виде значений массивы, то есть нам не обязательно передавать поочередно имена компьютеров.
Функция будет принимать массив с именами компьютеров и возвращать все остановленные сервисы. Я так же объявлю этот тип строгим, для наглядности, хотя и без этого в любом случае сработает:
Массивы так же работают по индексам, что позволяет передавать больше параметров. Такой способ не релевантный, но может когда-то пригодиться.
Хэш таблицы
Параметры хэш таблиц и могут передаваться не просто в функцию, а как параметры командлетов. Добавим в нашу функцию запуск сервиса, если он остановлен:
Знак @ в команде объявляет, что данные хэш таблицы будут использоваться как параметры команды. Важно, чтобы их имена соответствовали настоящим параметрам.
Условия
Нет никаких ограничений на использования условий. Это бывает достаточно удобно, когда функция должна вернуть разные значения.
Ниже приведен пример, где в зависимости от скорости загрузки основной части сайта будет возвращен разный ответ. Если скорость ответа меньше 76 миллисекунды нормальная, в случае если более долгого ответа вернется другой результат:
Switch
Мы уже говорили про Powershell Switch в предыдущих статьях. Если коротко, то это более удобные условия. Используя предыдущий пример, но со Switch, это будет выглядеть так:
Другой пример Switch это вызов функции в зависимости от переданных параметров. На примере ниже я вызываю функцию, в которой находится Switch. В эту функцию я передаю имя компьютера, которое проверяется на упоминание указанных фраз и вызывает соответствующую функцию. Каждая функция, которая устанавливает обновления, возвращает значение в Switch, а затем происходит return внутри нее:
Передача через конвейер или Pipeline
Вы наверняка работали через команды Powershell, которые позволяли использовать конвейер следующим образом:
Если мы захотим использовать подход описанный выше, создав новые команды в виде функций, то конвейер не будет работать:
Выполнив следующую команду мы сможем увидеть, что значения, которые могут приниматься через конвейер помечаются специальным атрибутом:
Таких атрибутов всего два:
Кроме этого, внутри нашей функции, мы должны добавить специальный блок Process. Наш скрипт в итоге будет выглядеть так:
Если бы мы не указали блок Process функция бы вернула только последней результат из массива 1..5:
Если наши команды будут иметь критический характер, такой как удаление, или через конвейер может передаваться несколько значений, то стоит использовать атрибут ValueFromPipelineByPropertyName. Таким образом мы исключим попадания через конвейер случайного значения. На примере ниже я изменил
Как уже писалось ValueFromPipelineByPropertyName принимает только именованные параметры и в случае с именем «bad» мы получаем ошибку:
Причем передавать именованные параметры через хэш таблицы мы не можем, только через pscustomobject.
Вы можете указывать сразу два атрибута таким образом:
Это позволит использовать и значение с именем, если оно указано либо без него. Это не спасет вас от ситуации, если вы передаете параметр с другим именем:
Передача через конвейер нескольких значений
Для примера рассмотрим ситуацию, где нам нужно передать через конвейер два значения. Если Get-SomeNum будет возвращать массив, то через конвейер у нас будет проходить каждое число по отдельности. Это еще один повод использовать именованные параметры:
Комментарии, описание и synopsis
При вызове справки на любой командлет мы получим такую информацию:
Описание функции, так же как и ее именование относится к рекомендованным действиям. Что бы это сделать нужно после объявления функции заполнить соответствующий блок. Я заполнил этот блок для одного из примеров:
Некоторые виды описаний, например Examples, можно использовать несколько раз.
Как перезагрузить компьютер удаленно через Powershell
Сохранение, загрузка и импорт
Скорее всего нашу функцию или готовый командлет мы захотим использовать и далее. В зависимости от ситуации мы должны сохранять и загружать его разными способами.
Импорт на множество компьютеров
Если это командлет, который будет использоваться на множестве компьютеров или вы его планируете использовать короткое время, то скрипт можно сохранить в файл с расширением «.ps1». Загрузка такой функции будет выполняться так:
После выполнения этой команды мы сможем использовать нашу функцию.
Минус такого способа в том, что нужно будет делать каждый раз после закрытия консоли (сессии).
Такой подход хорошо подходит в удаленных сценариях, когда на компьютерах пользователей нужно сделать какую-то работу.
Загрузка как модуля
Если вы планируете использовать функцию на своем компьютере, то вы можете загрузить эту команду как модуль. Вы можете использовать и на других компьютерах, но я считаю это плохим вариантом.
Первое что нужно сделать это получить пути окружения Powershell:
Выберете один из путей, где лежат модули или перейдите по следующему:
В указанной папке Modules вам нужно создать папку и файл с одинаковыми именами. Файлу добавляете расширение «.psm1» и помещаете в него свой скрипт.
В моём случае путь выглядит так:
После этого закройте все окна Powershell и откройте заново. Модуль будет импортироваться автоматически. Проверти что он загружен можно с помощью команды:
Что такое Windows PowerShell и с чем его едят? Часть 3: передача параметров в скрипты и функции, создание командлетов
Во второй части цикла рассматривались основы языка программирования PowerShell, а сейчас стоит разобраться с использованием написанного на нем кода для задач администрирования. Самый очевидный способ это сделать — запустить сценарий. Кроме него существует возможность создания собственных командлетов.
Оглавление:
Позиционные параметры
В функциях позиционные параметры используются аналогично:
Print-Args «Ноль» «Один»
Описанный выше способ позволяет передать в сценарий или функцию любое количество параметров, но при вызове необходимо соблюдать порядок их следования, а обращаться к ним можно только по индексу массива — это не всегда удобно.
Блок Param()
В сценариях и функциях намного удобнее использовать именованные параметры. В предыдущей статье мы рассказывали об одном способе их описания:
Корпорация Microsoft рекомендует использовать блок Param() — этот синтаксис более универсален и позволяет задавать не только аргументы функций, но и параметры сценариев:
В теле функции это выглядит так:
Если список аргументов функции невелик, блок Param() только загромоздит конструкцию, но во многих случаях он делает код более читаемым и является помимо прочего элементом хорошего стиля программирования.
Дополнительные атрибуты параметров
При описании аргументов функции или параметров скрипта можно задать их дополнительные атрибуты. Самый простой пример — принудительная установка типа:
Помимо приведения типов можно использовать атрибут [parameter()]:
С его помощью нетрудно сделать параметр обязательным. Обратите внимание на одновременное использование нескольких атрибутов — в этом случае они идут друг за другом:
Position позволяет указать порядок следования параметра (по умолчанию он соответствует порядку объявления):
У атрибута [Parameter()] есть и другие аргументы, полный список которых доступен на сайте Microsoft. Там же описаны прочие атрибуты, с помощью которых можно провести валидацию переданных значений, проверить их с использованием регулярных выражений и т.д. Перечислим некоторые:
[Alias()] устанавливает псевдоним для параметра:
Оператор приведения типов [string[]] означает, что значение параметра — строковый массив.
[AllowEmptyString()] разрешает пустую строку в качестве обязательного параметра:
[AllowEmptyCollection()] разрешает пустой массив в качестве обязательного параметра:
[ValidatePattern()] проверка с использованием регулярного выражения:
[ValidateLength()] проверяет длину строкового параметра:
Передача параметров через конвейер
В первой статье цикла мы рассказывали о возможности передачи данных в командлеты через конвейер (pipeline). В PowerShell командлеты и функции возвращают объекты или массивы объектов (результаты стейтментов), а также получают их на входе. Чтобы это увидеть, препарируем один из командлетов при помощи Get-Help:
ValueFromPipelineByPropertyName обычно используют при необходимости передать несколько параметров, чтобы не возникало путаницы, при этом аргумент можно применять одновременно с ValueFromPipeline:
Как видите, получать параметры через конвейер могут и скрипты, но все же практическое применение описанных выше атрибутов характерно скорее для расширенных функций, которые будут рассмотрены ниже.
Структура тела функции
В языке PowerShell функция может включать три необязательных блока заключенного в операторные скобки кода — Begin, Process и End. Выглядит она примерно так:
Атрибут [CmdletBinding()] и расширенные функции
Параметр -Force применяется для подавления запросов на проведение различных операций;
-WhatIf нужен для эмуляции запуска и отображения информации о последствиях выполнения функции (команды) без этого параметра. Обычно используется, если функция может выполнить деструктивные действия.
-Confirm требует подтверждения и также используется, если функция может выполнить деструктивные действия.
Low — функция незначительно воздействует на систему и не создает существенных рисков потери данных.
Medium — среднее воздействие с незначительным риском потери данных в результате деструктивных действий.
High — код создает высокий риск потери данных в результате деструктивных действий.
Модули сценариев и создание командлетов
Стандартный набор выглядит примерно так:
C:\Users\%UserName%\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\System32\WindowsPowerShell\v1.0\Modules
В этой статье мы достаточно подробно разобрали передачу параметров в функции и скрипты. Следующая часть цикла будет посвящена объектно-ориентированному программированию.