ChatGPT解决这个技术问题 Extra ChatGPT

在 PowerShell 中提示用户输入

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

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

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


P
Peter Mortensen

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。接受的答案是唯一一个真正回答我主要问题的人! ;) 所有其他信息也确实很有帮助,尤其是当我仍在摸索 PS 时。
没问题,@AJ。另一种获取方法信息的方法是去掉括号。我将在我的答案中添加一个示例。
仅供参考,如果您获得用户名和密码,您也可以使用 Get-Credential。
P
Peter Mortensen

使用参数绑定绝对是这里的方法。它不仅写起来非常快(只需在您的强制参数上方添加 [Parameter(Mandatory=$true)]),而且它也是您以后不会讨厌自己的唯一选择。

更多内容如下:

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

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

您正在尝试询问参数。

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

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


这是最灵活且用户友好的解决方案,但我几乎忽略了您的建议,因为没有像 Rynant's 答案中那样清晰的代码示例。你能提供一些格式很好的例子吗?
“很简单,Read-Host 是一种糟糕的形式”......除非您使用它来有条件地接受因为有人没有使用任何参数调用您的脚本而被遗漏的输入。繁荣。
不:那么它仍然是糟糕的形式。这就是您将参数标记为强制的原因。
如果你想写一个交互式脚本怎么办?假设它是一个脚本,仅在满足某些条件时才需要用户输入。例如,如果您的脚本要为 SDK 设置目标目录,您可能需要确认用户想要删除该目录(如果该目录已存在)。
我认为 user1499731 有一个很好的观点......有时您需要从用户那里获取输入,而这些输入只有在显示某些信息或执行另一个操作之后才能有意义地提供。在这种情况下,您不能使用参数,并且此处给出的 Read-Host 是“错误形式”的原因不适用。此外,.ShouldProcess() 具有 Read-Host 没有的限制,例如仅限于几个答案。但是,我同意 .ShouldProcess() 在适用时更好。
A
ANeves

将其放在脚本的顶部。它将导致脚本提示用户输入密码。然后可以通过 $pw 在脚本的其他地方使用生成的密码。

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

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

如果要调试并查看刚刚读取的密码的值,请使用:

   write-host $pw

佚名

作为替代方案,您可以将其添加为脚本参数以作为脚本执行的一部分进行输入

 param(
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value1,
      [Parameter(Mandatory = $True,valueFromPipeline=$true)][String] $value2
      )