Linux has have stty -echo
which make off typing so it is not echoed back to user.
So basically what you're typing is not seen on the shell.
Is there way to do the same in powershell
?
Linux has have stty -echo
which make off typing so it is not echoed back to user.
So basically what you're typing is not seen on the shell.
Is there way to do the same in powershell
?
As it turns out, your intent was to suppress echoing of commands provided via stdin to the PowerShell CLI (powershell.exe
for Windows PowerShell, pwsh
for PowerShell (Core) 7+):
To do so, use -Command -
(-c -
), which - like -File -
(-f -
, the default behavior) - accepts (independent) commands one by one via stdin, but - unlike -File -
- neither prints a prompt string nor echoes the command provided:
-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>
Note: In the examples above, a single command is provided via stdin (via the pipeline), and since no more stdin input is provided, the PowerShell process exits. However, in scenarios where you keep stdin open, you'll be able to feed commands - one by one - to the PowerShell process indefinitely.
Caveat: Both -File -
and -Command -
exhibit problematic, pseudo-interactive behavior; notably, a command spanning multiple lines must be terminated with two newlines; see GitHub issue #3223 for details.
Note:
Providing neither -Command -
nor -File -
is essentially the same as -File -
, except that a copyright message is also printed on startup (which can be suppressed separately with -NoLogo
); in short: ... | powershell -NoLogo
is the same as
... | powershell -File -
To provide a predictable execution environment and to avoid extra overhead, consider preceding -File
/ -Command
with -NoProfile
, which bypasses the loading of PowerShell's profile files.
As for a general stty -echo
equivalent (the POSIX-mandated stty
utility is available on Unix-like platforms, not on Windows):
bash
does not try to reset the terminal to its previous state after issuing this command, so input typed by the user indeed remains invisible through the end of the session or until the terminal is reset.stty -echo
is, in effect, a no-op.On a loosely related note (prompted by a misreading of the question's intent), the following discusses:
Read-Host
cmdlet:There is no built-in PowerShell feature (as of v7.2) that hides what the user types, but if the intent is simply to mask user input, so as to hide sensitive information being typed, such as a password, you have two options - both of which mask each character typed printing *
instead:
Use Read-Host
-AsSecureString
:
$$valueEnteredSecure = Read-Host -AsSecureString -Prompt 'Enter your password'
Note that this outputs a System.Security.SecureString
instance (which provides limited security on Windows, and virtually none on Unix-like platforms), which you can convert back to a regular string as follows:
$valueEntered = [System.Net.NetworkCredential]::new('', $valueEnteredSecure).Password
In PowerShell (Core) 7.0+, you can alternatively use (though note the simpler 7.1+ solution further below):
$valueEntered = ConvertFrom-SecureString $valueEnteredSecure -AsPlainText
PowerShell (Core) 7.1+ now supports a -MaskInput
parameter that exhibits the same UI behavior, but directly returns a regular string:
# PowerShell 7.1+
$valueEntered = Read-Host -MaskInput -Prompt 'Enter your password'
If truly suppressing the display of all characters typed by the user is a must, you'll have to create a custom solution that uses $host.ui.RawUI.ReadKey('NoEcho')
in a loop:
Here's a simple implementation, which you can call as
$valueEntered = Read-HostSilent -Prompt 'Enter your password'
, for instance:
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
}