Запрашивать ввод пользователя в PowerShell

209

Я хочу попросить пользователя ввести ряд данных, включая пароль и имя файла.

У меня есть пример использования host.ui.prompt, который кажется разумным, но я не могу понять обратное.

Есть ли лучший способ получить пользовательский ввод в PowerShell?

AJ.
источник

Ответы:

333

Read-Host это простая опция для получения ввода строки от пользователя.

$name = Read-Host 'What is your username?'

Чтобы скрыть пароли, вы можете использовать:

$pass = Read-Host 'What is your password?' -AsSecureString

Чтобы преобразовать пароль в обычный текст:

[Runtime.InteropServices.Marshal]::PtrToStringAuto(
    [Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass))

Что касается типа, возвращаемого пользователем $host.UI.Prompt(), если вы запустите код по ссылке, размещенной в комментарии @ Christian, вы можете узнать тип возвращаемого значения, отправив его по адресу Get-Member(например, $results | gm). В результате получается словарь, в котором ключ - это имя FieldDescriptionобъекта, используемого в приглашении. Чтобы получить доступ к результату для первой строки в связанном примере введите: $results['String Field'].

Чтобы получить доступ к информации без вызова метода, оставьте скобки выключенными:

PS> $Host.UI.Prompt

MemberType          : Method
OverloadDefinitions : {System.Collections.Generic.Dictionary[string,psobject] Pr
                    ompt(string caption, string message, System.Collections.Ob
                    jectModel.Collection[System.Management.Automation.Host.Fie
                    ldDescription] descriptions)}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : System.Collections.Generic.Dictionary[string,psobject] Pro
                    mpt(string caption, string message, System.Collections.Obj
                    ectModel.Collection[System.Management.Automation.Host.Fiel
                    dDescription] descriptions)
Name                : Prompt
IsInstance          : True

$Host.UI.Prompt.OverloadDefinitionsдаст вам определение (я) метода. Каждое определение отображается как <Return Type> <Method Name>(<Parameters>).

Rynant
источник
Спасибо, @Rynant. Принял ответ за то, что был единственным, кто действительно ответил на мой главный вопрос! ;) Вся остальная информация тоже очень полезна, тем более что я все еще нащупываю свой путь в PS.
AJ.
Нет проблем, @AJ. Еще один способ получить информацию о методе - это оставить скобки. Я добавлю пример к моему ответу.
Rynant
3
К вашему сведению, вы также можете использовать Get-Credential, если вы получаете имена пользователей и пароли.
Мэтт Лайонс
75

Использование привязки параметров определенно является подходом. Это не только очень быстро написать (просто добавьте [Parameter(Mandatory=$true)]над обязательными параметрами), но это также единственный вариант, который вы не будете ненавидеть себя позже.

Больше ниже:

[Console]::ReadLineявно запрещено правилами FxCop для PowerShell. Зачем? Поскольку он работает только в PowerShell.exe, а не в PowerShell ISE , PowerGUI и т. Д.

Read-Host , довольно просто, плохая форма. Read-Host бесконтрольно останавливает сценарий для запроса пользователя, что означает, что у вас никогда не будет другого сценария, который включает сценарий, использующий Read-Host.

Вы пытаетесь запросить параметры.

Вы должны использовать [Parameter(Mandatory=$true)]атрибут и правильно набрать, чтобы запросить параметры.

Если вы используете это на [SecureString], он запросит поле пароля. Если вы используете это для типа учетных данных ( [Management.Automation.PSCredential]), появится диалоговое окно учетных данных, если параметр отсутствует. Строка станет просто старым текстовым полем. Если вы добавите HelpMessage к атрибуту параметра (то есть [Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]), он станет текстом справки для приглашения.

Start-Automating
источник
5
Это наиболее гибкое и удобное решение, но я почти проигнорировал ваш совет, потому что не было четких примеров кода, как в ответе Ринанта . Можете ли вы привести несколько хорошо отформатированных примеров?
Иэн Самуэль Маклин, старейшина
4
«Read-Host - это просто плохая форма» ... если вы не используете его для условного принятия ввода, который был пропущен, потому что кто-то не вызывал ваш скрипт с ЛЮБЫМИ параметрами. БУМ.
2
Нет, тогда это все еще плохая форма. Вот почему вы отмечаете параметры как обязательные.
Старт-автоматизация
2
Что если вы хотите написать интерактивный скрипт? Скажем, это скрипт, который требует ввода пользователя только при соблюдении определенных условий. Например, если ваш сценарий предназначен для установки целевого каталога для SDK, вы можете подтвердить, что пользователь хочет удалить каталог, если он уже существует.
Джейсон Гомаат
6
Я думаю, что у user1499731 было хорошее замечание ... Бывают моменты, когда вам нужно принять ввод от пользователя, который может быть предоставлен только после того, как будет отображена некоторая информация или будет выполнена другая операция. В этом случае вы не можете использовать параметр, и причины, приведенные здесь Read-Hostкак «плохая форма», не применяются. Более того, .ShouldProcess()есть ограничения, которых Read-Hostнет, такие как ограниченность несколькими ответами. Однако я согласен, что .ShouldProcess()лучше, когда это применимо.
LarsH
14

Поместите это в верхней части вашего сценария. Это заставит скрипт запросить у пользователя пароль. Полученный пароль можно затем использовать в другом месте вашего скрипта через $ pw .

   Param(
     [Parameter(Mandatory=$true, Position=0, HelpMessage="Password?")]
     [SecureString]$password
   )

   $pw = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))

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

   write-host $pw
user2334160
источник
3

В качестве альтернативы вы можете добавить его в качестве параметра скрипта для ввода как части выполнения скрипта

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
инакомыслящий
источник