20

I'm using Console.ReadLineto read the input of the user. However, I want to hide/exclude the inputted text on the console screen while typing. For example, when the user writes "a", it writes "a" to the console and then I will have a variable with the value "a". However, I don't want "a" to be written on the console's output.

How can I do that?

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
user3265040
  • 305
  • 1
  • 4
  • 11
  • 1
    `Console.ReadLine` is setup in a way that it echoes the input straight back to the console. For special-use cases (like if you wanted to enter a password and didn't want people to see the letters typed), you must capture the characters one-by-one (as @ojblass pointed out) and store them into a variable yourself. Or if you prefer, you can display a series of '*' out to the console's output, or even replace them with flying monkeys if you want. – OnlineCop May 02 '14 at 18:04
  • 1
    Related: http://stackoverflow.com/q/3404421/945456 – Jeff B Feb 26 '15 at 14:38

8 Answers8

43

Here is a short implementation. thx @ojblass for the idea

System.Console.Write("password: ");
string password = null;
while (true)
{
    var key = System.Console.ReadKey(true);
    if (key.Key == ConsoleKey.Enter)
        break;
    password += key.KeyChar;
}
dataCore
  • 1,509
  • 1
  • 16
  • 17
  • 7
    might be better to use a stringbuilder – m4tt1mus May 04 '17 at 18:22
  • 3
    @m4tt1mus I disagree. StringBuilder is only a performance boost when doing a large amount of string concatenation. Typing a password is not a large amount. Using StringBuilder would just add unnecessary extra code. – CathalMF Feb 17 '19 at 20:50
  • @CathalMF "Opinions vary on just how many strings you have to concatenate before you should start worrying about performance. The general consensus is around 10." https://blog.codinghorror.com/the-sad-tragedy-of-micro-optimization-theater/ – m4tt1mus Feb 18 '19 at 02:26
  • 4
    @m4tt1mus Yes but not when we wait for user entry on each loop. It would have to be an unbroken loop to matter. – CathalMF Feb 18 '19 at 07:00
  • And what about pressing Ctrl-V to paste the text? Will the program receive the symbols as if they were typed in or will it receive just Ctrl-V key codes? – JustAMartin Aug 28 '20 at 11:11
  • 1
    @JustAMartin Works with "Ctr+C/Ctrl+V". Made a short test (dotnet core console app). – dataCore Aug 31 '20 at 07:43
19

Console.ReadKey(true) hides the user key. I do not believe Console.Read() offers such a capability. If necessary you can sit in a loop reading keys one at a time until enter is pressed. See this link for an example.

ojblass
  • 21,146
  • 22
  • 83
  • 132
9

I created this method from the code in the answer by dataCore and the suggestion by m4tt1mus. I also added support for the backspace key.

private static string GetHiddenConsoleInput()
{
    StringBuilder input = new StringBuilder();
    while (true)
    {
        var key = Console.ReadKey(true);
        if (key.Key == ConsoleKey.Enter) break;
        if (key.Key == ConsoleKey.Backspace && input.Length > 0) input.Remove(input.Length - 1, 1);
        else if (key.Key != ConsoleKey.Backspace) input.Append(key.KeyChar);
    }
    return input.ToString();
}
Peet
  • 697
  • 9
  • 9
2

I just changed the foreground colour to black while the password was being inputted. I a newbie so it's probably a bad idea but it worked for the challenge i was trying

Console.WriteLine("Welcome to our system. Please create a UserName");
        var userName = Console.ReadLine();
        Console.WriteLine("Now please create a password");
        Console.ForegroundColor = ConsoleColor.Black;
        var password = Console.ReadLine();
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("Okay, let's get you logged in:");
2
private static string GetPassword()
    {
        StringBuilder input = new StringBuilder();
        while (true)
        {
            int x = Console.CursorLeft;
            int y = Console.CursorTop;
            ConsoleKeyInfo key = Console.ReadKey(true);
            if (key.Key == ConsoleKey.Enter)
            {
                Console.WriteLine();
                break;
            }
            if (key.Key == ConsoleKey.Backspace && input.Length > 0)
            {
                input.Remove(input.Length - 1, 1);
                Console.SetCursorPosition(x - 1, y);
                Console.Write(" ");
                Console.SetCursorPosition(x - 1, y);
            }
            else if (key.Key != ConsoleKey.Backspace)
            {
                input.Append(key.KeyChar);
                Console.Write("*");
            }
        }
        return input.ToString();
    }
1

For the sake of showing something different to the previous solutions and seeing as I love a good simple and dirty solution..

// Take input character
val = Console.ReadKey().KeyChar;
// Remove entered character from console
Console.Write("\b \b");

Obviously wrap in a loop and etc etc.

Very late to the party I know and a much less elegant solution compared with the rest but hopefully this might help someone in future.

nChristos
  • 11
  • 2
1

If you just want to keep your neighbor from reading the password you can also play with the foreground color:

Console.Write("Enter root password:")
Dim oldColor As ConsoleColor = Console.ForegroundColor
Console.ForegroundColor = Console.BackgroundColor
rootPW = Console.ReadLine()
Console.ForegroundColor = oldColor
Stefan Meyer
  • 889
  • 1
  • 9
  • 19
0

Improved version from @Fredrik Fjällström post: https://stackoverflow.com/a/59668053/2935383

His version is great because you can also see the cursor and set password-*** char if necessary. But what is still missing is the suppression of non-printable characters.

    public static string GetPassword()
    {
        StringBuilder input = new StringBuilder();
        while (true)
        {
            int x = Console.CursorLeft;
            int y = Console.CursorTop;
            ConsoleKeyInfo key = Console.ReadKey(true);
            if (key.Key == ConsoleKey.Enter)
            {
                Console.WriteLine();
                break;
            }
            if (key.Key == ConsoleKey.Backspace && input.Length > 0)
            {
                input.Remove(input.Length - 1, 1);
                Console.SetCursorPosition(x - 1, y);
                Console.Write(" ");
                Console.SetCursorPosition(x - 1, y);
            }
            else if( key.KeyChar < 32 || key.KeyChar > 126 )
            {
                Trace.WriteLine("Output suppressed: no key char"); //catch non-printable chars, e.g F1, CursorUp and so ...
            }
            else if (key.Key != ConsoleKey.Backspace)
            {
                input.Append(key.KeyChar);
                Console.Write("*");
            }
        }
        return input.ToString();
    }
raiserle
  • 677
  • 8
  • 31