有没有办法在`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
}
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-mandatedstty
实用程序可用在类 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
}