【问题标题】:Is there way to turn off `ECHO` user input in `powershell`有没有办法在`powershell`中关闭`ECHO`用户输入
【发布时间】:2021-09-04 09:57:10
【问题描述】:

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

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

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

【问题讨论】:

  • 用例是什么?输入密码?
  • @ThomasWeller 不,这不是重复的。 echo onecho off 控制批处理文件中文本的回显,而不是用户输入的文本

标签: windows powershell winapi


【解决方案1】:

事实证明,您的意图是抑制将通过标准输入提供的命令回显到 PowerShell CLIpowershell.exe for Windows PowerShell,pwsh for PowerShell (Core) 7+):

为此,使用-Command - (-c -),它 - like -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>

注意:在上面的示例中,single 命令是通过 stdin(通过管道)提供的,并且由于不再提供 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。
    • 类似bash 的 POSIX 兼容 shell不会在发出此命令后尝试将终端重置为之前的状态,因此用户输入的输入在会话或直到终端重置。
    • 相比之下,PowerShell(在类 Unix 平台上运行的跨平台 v7+ 版本)确实在运行每个命令后重置终端,因此运行 stty -echo 实际上是不-op。
    • 换句话说:您无法在任何平台上(至少从 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 平台上几乎没有),您可以将其转换回常规字符串,如下所示:

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

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

$valueEntered = ConvertFrom-SecureString $valueEnteredSecure -AsPlainText

PowerShell (Core) 7.1+ 现在支持显示相同 UI 行为的 -MaskInput 参数,但直接返回常规字符串

# 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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 2020-04-07
    • 2021-11-08
    相关资源
    最近更新 更多