I’m working on a simple command-line app, and have the need to collect a username and password. I don’t want the password to be printed on the screen as they type, but System.Console.ReadLine doesn’t seem to have any option to mask the input before it’s echoed back to the console.
There are a couple ways I found to resolve this, the easy way, and the harder way with better UI.
Easy way:
[csharp]
ConsoleColor oldFore = Console.ForegroundColor;
Console.ForegroundColor = Console.BackgroundColor;
string password = Console.ReadLine();
Console.ForegroundColor = oldFore;
[/csharp]
This basically hides the echoed input by setting the text color to be the same as the background color. This is a little weird because your users can’t see any indication that they’ve entered any information.
The following function catches the input, and then echoes “*” instead. There’s some rudimentary handling of backspace, but no other special keys (end, delete, arrow keys, etc) are handled properly. For now it’s good enough for my use:
[csharp]
public static string ReadPassword() {
Stack
//keep reading
for (ConsoleKeyInfo cki = Console.ReadKey(true); cki.Key != ConsoleKey.Enter; cki = Console.ReadKey(true)) {
if (cki.Key == ConsoleKey.Backspace) {
//rollback the cursor and write a space so it looks backspaced to the user
Console.SetCursorPosition(Console.CursorLeft – 1, Console.CursorTop);
Console.Write(” “);
Console.SetCursorPosition(Console.CursorLeft – 1, Console.CursorTop);
passbits.Pop();
}
else {
Console.Write(“*”);
passbits.Push(cki.KeyChar.ToString());
}
}
string[] pass = passbits.ToArray();
Array.Reverse(pass);
return string.Join(string.Empty, pass);
}
[/csharp]
A bit messy and bug-ridden, but for now it’s good enough for my purposes. When C# 3 comes out, I might be able to add things like this to the Console class using extension methods. Maybe a community-driven FrameworkPlus library will get some momentum, and we can all ditch our home-grown Utils libraries and reap the benefits of each other’s work.
14 Comments