1

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?

Zhiburt
  • 65
  • 2
  • 6

1 Answers1

2

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:

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

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

  • With -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):

    • This commands operates on the terminal, not the shell that happens to run in it.
    • A POSIX-compatible shell such as 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.
    • By contrast, PowerShell (the cross-platform v7+ edition that runs on Unix-like platforms) does reset the terminal after running each command, so running stty -echo is, in effect, a no-op.
    • In other words: you cannot achieve the same effect in PowerShell, on any platform (at least as of PowerShell 7.2)

On a loosely related note (prompted by a misreading of the question's intent), the following discusses:

How to hide or mask interactive user input solicited via the 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
}
mklement0
  • 382,024
  • 64
  • 607
  • 775