在PowerShell中提示用户输入


209

我想提示用户一系列输入,包括密码和文件名。

我有一个使用的示例host.ui.prompt,这似乎很明智,但我无法理解返回值。

有没有在PowerShell中获得用户输入的更好方法?

Answers:


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)来查找返回类型。结果是一个Dictionary,其中的键是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。是唯一实际回答我的主要问题的答案!;)所有其他信息也确实有帮助,尤其是在我仍在探索PS的过程中。
AJ。

没问题,@ AJ。获取有关方法的信息的另一种方法是省略括号。我将在示例中添加一个示例。
雷纳特2011年

3
仅供参考,如果您要获取用户名和密码,也可以使用Get-Credential。
马特·里昂斯

75

使用参数绑定绝对是解决问题的方法。不仅编写起来非常快(只需[Parameter(Mandatory=$true)]在必需参数上方添加),它也是以后不会讨厌自己的唯一选择。

以下内容:

[Console]::ReadLinePowerShell 的FxCop规则明确禁止。为什么?因为它仅适用于PowerShell.exe,不适用于PowerShell ISEPowerGUI等。

读主机很简单,是一种不好的形式。Read-Host无法控制地停止脚本以提示用户,这意味着您永远不会拥有包含使用Read-Host的脚本的其他脚本。

您正在尝试询问参数。

您应该使用该[Parameter(Mandatory=$true)]属性并正确键入以要求输入参数。

如果在上使用此[SecureString]密码,则会提示您输入密码字段。如果在凭据类型([Management.Automation.PSCredential])上使用此选项,则该参数不存在时将弹出凭据对话框。字符串将变成一个普通的旧文本框。如果将HelpMessage添加到参数属性(即),[Parameter(Mandatory = $true, HelpMessage = 'New User Credentials')]则它将成为提示的帮助文本。


5
这是最灵活和用户友好的解决方案,但是我几乎忽略了您的建议,因为没有像Rynant的答案那样清晰的代码示例。您能否提供一些格式正确的示例?
伊恩·塞缪尔·麦克莱恩

4
“读取主机,很简单,是一种错误的格式” ...除非您使用它来有条件地接受由于某人未使用ANY参数调用您的脚本而遗漏的输入。繁荣。

2
不:那仍然是不好的形式。这就是为什么将参数标记为必需的原因。
开始自动化

2
如果编写交互式脚本怎么办?说这是一个脚本,仅在满足某些条件时才需要用户输入。例如,如果脚本要为SDK设置目标目录,则可能要确认用户是否要删除该目录(如果已存在)。
詹森·古玛

6
我认为user1499731有一个优点...有时您需要从用户那里获取输入,而这些输入只有在显示某些信息或执行其他操作之后才能有意义地提供。在这种情况下,您不能使用参数,并且此处给出的Read-Host“格式错误” 的原因也不适用。而且,.ShouldProcess()Read-Host没有限制,例如仅限于一些答案。但是,我同意.ShouldProcess(),在适用时会更好。
LarsH '16

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

3

或者,您可以将其添加为脚本参数,以作为脚本执行的一部分进行输入

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.