有没有办法在`powershell`中关闭`ECHO`用户输入

Is there way to turn off `ECHO` user input in `powershell`

Linux 有 stty -echo 可以避免输入,因此不会回显给用户。

所以基本上您输入的内容在 shell 上是看不到的。

有没有办法在 powershell 中做同样的事情?

事实证明,您的意图是 抑制通过标准输入 向 PowerShell CLI 提供的命令回显 powershell.exe for Windows PowerShell, pwsh 对于 PowerShell(核心)7+):

为此,使用 -Command - (-c -),这 - 喜欢 -File --f -,默认行为)- 通过标准输入一个接一个地接受(独立的)命令,但是 - 不像 -File - - 既不打印 提示字符串 也不回应提供的命令:

  • -Command -:
# OK: Just the piped command's *output* prints.
PS> 'Get-Date' | powershell.exe -Command -

Friday, September 3, 2021 10:08:07 AM

  • -File -:
# Pseudo-interactive behavior:
# The piped command's output is: 
#  * *preceded by* the prompt string as well as the input command.
#  * *followed by* another rendering of the prompt string.
PS> 'Get-Date' | powershell.exe -File -

PS C:\Users\jdoe> Get-Date

Friday, September 3, 2021 10:09:44 AM

PS C:\Users\jdoe>

注意:在上面的示例中,通过 stdin(通过管道)提供了 single 命令,并且由于没有提供更多的 stdin 输入,PowerShell 进程退出。但是,在您 保持标准输入打开 的情况下,您将能够无限期地向 PowerShell 进程一个接一个地提供命令。

警告 -File --Command - 都表现出有问题的伪交互行为;值得注意的是,跨越多行的命令必须以 two 换行符终止;有关详细信息,请参阅 GitHub issue #3223

注:

  • 提供 -Command --File - 本质上与 -File - 相同,除了版权信息是也在启动时打印(可以用 -NoLogo 单独抑制);简而言之:... | powershell -NoLogo
    相同 ... | powershell -File -

  • 为了提供可预测的执行环境并避免额外的开销,请考虑在 -File / -Command 之前加上 -NoProfile,这会绕过 PowerShell 的 profile files.

  • 至于 一般 stty -echo 等效POSIX-mandated stty 实用程序可用在类 Unix 平台上,而不是 Windows):

    • 此命令在 终端 上运行,而不是 shell 上的 运行。
    • A POSIX-compatible shell such as bash does not try to reset the terminal to its previous state after issued this command , 因此用户键入的输入在会话结束或终端重置之前确实保持不可见。
    • 相比之下,PowerShell(运行在类 Unix 平台上的跨平台 v7+ 版本) 会在 运行ning 后重置终端每个命令,所以 运行ning stty -echo 实际上是一个空操作。
    • 换句话说:您无法在任何平台(至少从 PowerShell 7.2 开始)的 PowerShell 中实现相同的效果

在松散相关的注释中(由于对问题意图的误读而提示),以下讨论:

如何隐藏或屏蔽通过 Read-Host cmdlet 请求的交互式用户输入:

没有 内置的 PowerShell 功能(从 v7.2 开始)隐藏 用户键入的内容,但是如果目的只是屏蔽用户输入,以便隐藏正在键入的敏感信息,例如密码,您有两个选择 - 两个屏蔽每个键入的字符打印 * 而不是:

使用Read-Host-AsSecureString:

$$valueEnteredSecure = Read-Host -AsSecureString -Prompt 'Enter your password'

请注意,这会输出一个 System.Security.SecureString 实例(在 Windows 上提供有限的安全性,在类 Unix 平台上几乎 none),您可以将其转换回常规字符串如下:

$valueEntered = [System.Net.NetworkCredential]::new('', $valueEnteredSecure).Password

PowerShell (Core) 7.0+ 中,您也可以使用(请注意下面更简单的 7.1+ 解决方案):

$valueEntered = ConvertFrom-SecureString $valueEnteredSecure -AsPlainText

PowerShell (Core) 7.1+ 现在支持表现出相同 UI 行为的 -MaskInput 参数, 但 直接 returns 一个常规字符串 :

# PowerShell 7.1+
$valueEntered = Read-Host -MaskInput -Prompt 'Enter your password'

如果必须抑制显示用户输入的所有字符,您必须创建自定义解决方案在循环中使用 $host.ui.RawUI.ReadKey('NoEcho')

这是一个简单的实现,您可以将其称为
$valueEntered = Read-HostSilent -Prompt 'Enter your password',例如:

function Read-HostSilent {
  param([string] $Prompt)
  if ($Prompt) { Write-Host -NoNewline "${Prompt}: " }
  $entered = $null; $done = $false
  do {
    $key = $host.ui.RawUI.ReadKey('NoEcho')
    switch ($key.VirtualKeyCode) {
      # Backspace
      8 { if ($entered.Length -gt 1) { $entered = $entered.Substring(0, $entered.Length-1) } }
      # Enter
      13 { $done = $true; break }
      default {
        if ($key.Character) { # printable?
          $entered += $key.Character
        }
      }
    }
  } while (-not $done)
  $entered # output
}