using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Windows.Forms; namespace RobvanderWoude { class MaskText { static string progver = "1.00"; static bool oddrow = true; static int Main( string[] args ) { string text = String.Empty; string mask = String.Empty; #region Command Line Arguments if ( args.Length == 0 ) { return ShowHelp( ); } if ( args.Length > 0 ) { if ( args[0] == "/?" ) { return ShowHelp( ); } if ( args[0].ToUpper( ) == "/M" ) { return ShowMaskHelp( ); } mask = args[0]; } if ( args.Length > 1 ) { if ( args[1] == "/?" ) { return ShowHelp( ); } if ( args[1].ToUpper( ) == "/M" ) { return ShowMaskHelp( ); } text = args[1]; } if ( args.Length > 2 ) { return ShowHelp( ); } #endregion Command Line Arguments if ( String.IsNullOrWhiteSpace( text ) ) { if ( ConsoleEx.InputRedirected ) { text = Console.In.ReadLine( ); } else { text = Console.ReadLine( ); } } try { MaskedTextBox textbox = new MaskedTextBox( mask ); textbox.Text = text; Console.Write( textbox.Text ); if ( textbox.MaskCompleted ) { return 0; } else { return 1; } } catch ( Exception e ) { return ShowHelp( e.Message ); } } static int ShowHelp( params string[] errmsg ) { #region Error Message if ( errmsg.Length > 0 ) { List errargs = new List( errmsg ); errargs.RemoveAt( 0 ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write( "ERROR:\t" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) ); Console.ResetColor( ); } #endregion Error Message /* Input.exe, Version 1.00 Apply a mask to input text Usage: MaskText.exe mask [ text ] or: command | MaskText.exe mask Where: mask is the mask to be applied to the input text (type MaskText.exe /M for help on the mask "language") text is the input text to be matched against the mask command is a console command whose output is piped as input text Notes: If text is specified on the command line, the program will ignore any piped input. If no text is specified on the command line, nor piped, the program will wait for typed input (no prompt). Whether interactive or piped, only one line of input text is accepted, i.e. everything including and following the first linefeed is ignored. Return code is 0 if the input text matches the mask, otherwise 1. Credits: Code to detect redirection by Hans Passant on StackOverflow.com: http://stackoverflow.com/a/3453272 Written by Rob van der Woude http://www.robvanderwoude.com */ #region Help Text Console.Error.WriteLine( ); Console.Error.WriteLine( "Input.exe, Version {0}", progver ); Console.Error.WriteLine( "Apply a mask to input text" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "MaskText.exe mask [ text ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( " or: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "command | MaskText.exe mask" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "mask " ); Console.ResetColor( ); Console.Error.Write( "is the " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "mask " ); Console.ResetColor( ); Console.Error.Write( "to be applied to the input " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "text" ); Console.ResetColor( ); Console.Error.Write( " (type " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "MaskText.exe /M " ); Console.ResetColor( ); Console.Error.WriteLine( " for help on the mask \"language\")" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " text " ); Console.ResetColor( ); Console.Error.Write( "is the input " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "text " ); Console.ResetColor( ); Console.Error.Write( "to be matched against the " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "mask" ); Console.ResetColor( ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " command " ); Console.ResetColor( ); Console.Error.Write( "is a console " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "command " ); Console.ResetColor( ); Console.Error.Write( "whose output is piped as input " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "text" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Notes: If " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "text " ); Console.ResetColor( ); Console.Error.WriteLine( "is specified on the command line, the program will ignore any" ); Console.Error.Write( " piped input. If no " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "text " ); Console.ResetColor( ); Console.Error.WriteLine( "is specified on the command line, nor piped," ); Console.Error.WriteLine( " the program will wait for typed input (no prompt)." ); Console.Error.Write( " Whether interactive or piped, only one line of input " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "text " ); Console.ResetColor( ); Console.Error.WriteLine( "is accepted," ); Console.Error.WriteLine( " i.e. everything including and following the first linefeed is ignored." ); Console.Error.WriteLine( " Return code is 0 if the input text matches the mask, otherwise 1." ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Credits: Code to detect redirection by Hans Passant on StackOverflow.com:" ); Console.ForegroundColor = ConsoleColor.DarkGray; Console.Error.WriteLine( " http://stackoverflow.com/a/3453272" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "http://www.robvanderwoude.com" ); #endregion Help Text return 1; } public static int ShowMaskHelp( ) { Console.Error.Write( "Help for this program's " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "mask " ); Console.ResetColor( ); Console.Error.WriteLine( "argument{0}(based on the Masked Edit control in Visual Basic 6.0):", ( Console.WindowWidth < 94 ? "\n" : " " ) ); Console.ForegroundColor = ConsoleColor.DarkGray; string url1 = "http://msdn.microsoft.com/en-us/library/"; string url2 = "system.windows.forms.maskedtextbox.mask.aspx#remarksToggle"; if ( url1.Length + url2.Length > Console.WindowWidth ) { Console.Error.WriteLine( url1 ); Console.Error.WriteLine( url2 ); } else { Console.Error.WriteLine( url1 + url2 ); } Console.ResetColor( ); Console.Error.WriteLine( ); oddrow = true; WriteTableRow( "Masking element", "Description", true, true ); oddrow = true; WriteTableRow( "===============", "===========", true, true ); WriteTableRow( "0", "Digit, required. This element will accept any single digit between 0 and 9." ); WriteTableRow( "9", "Digit or space, optional." ); WriteTableRow( "#", "Digit or space, optional. If this position is blank in the mask, it will be rendered as a space in the Text property. Plus (+) and minus (-) signs are allowed." ); WriteTableRow( "L", "Letter, required. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z] in regular expressions." ); WriteTableRow( "?", "Letter, optional. Restricts input to the ASCII letters a-z and A-Z. This mask element is equivalent to [a-zA-Z]? in regular expressions." ); WriteTableRow( "&", "Character, required. Any non-control character. If ASCII only is set (/A), this element behaves like the \"A\" element." ); WriteTableRow( "C", "Character, optional. Any non-control character. If ASCII only is set (/A), this element behaves like the \"a\" element." ); WriteTableRow( "A", "Alphanumeric, required. If ASCII only is set (/A), the only characters it will accept are the ASCII letters a-z and A-Z and numbers. This mask element behaves like the \"&\" element." ); WriteTableRow( "a", "Alphanumeric, optional. If ASCII only is set (/A), the only characters it will accept are the ASCII letters a-z and A-Z and numbers. This mask element behaves like the \"C\" element." ); WriteTableRow( ".", "Decimal placeholder." ); WriteTableRow( ",", "Thousands placeholder." ); WriteTableRow( ":", "Time separator." ); WriteTableRow( "/", "Date separator." ); WriteTableRow( "$", "Currency symbol." ); WriteTableRow( "<", "Shift down. Converts all characters that follow to lowercase." ); WriteTableRow( ">", "Shift up. Converts all characters that follow to uppercase." ); WriteTableRow( "|", "Disable a previous shift up or shift down." ); WriteTableRow( @"\", "Escape. Escapes a mask character, turning it into a literal. \"\\\\\" is the escape sequence for a backslash." ); WriteTableRow( "All other characters", "Literals. All non-mask elements will appear as themselves within MaskedTextBox. Literals always occupy a static position in the mask at run time, and cannot be moved or deleted by the user." ); return 1; } public static void WriteTableRow( string col1text, string col2text, bool col1bold = true, bool col2bold = false ) { // Wrap text to fit in 2 columns oddrow = !oddrow; int windowwidth = Console.WindowWidth; int col1width = 22; int col2width = windowwidth - col1width - 5; // Column separator = 4, subtract 1 extra to prevent automatic line wrap List col2lines = new List( ); // Column 2 if ( col2text.Length > col2width ) { Regex regex = new Regex( @".{1," + col2width + @"}(?=\s|$)" ); if ( regex.IsMatch( col2text ) ) { MatchCollection matches = regex.Matches( col2text ); foreach ( Match match in matches ) { col2lines.Add( match.ToString( ).Trim( ) ); } } else { while ( col2text.Length > 0 ) { col2lines.Add( col2text.Trim( ).Substring( 0, Math.Min( col2width, col2text.Length ) ) ); col2text = col2text.Substring( Math.Min( col2width, col2text.Length ) ).Trim( ); } } } else { col2lines.Add( col2text.Trim( ) ); } for ( int i = 0; i < col2lines.Count; i++ ) { if ( oddrow ) { Console.BackgroundColor = ConsoleColor.DarkGray; } if ( col1bold || oddrow ) { Console.ForegroundColor = ConsoleColor.White; } Console.Write( "{0,-" + col1width + "} ", ( i < 1 ? col1text : String.Empty ) ); Console.ResetColor( ); if ( oddrow ) { Console.BackgroundColor = ConsoleColor.DarkGray; } if ( col2bold || oddrow ) { Console.ForegroundColor = ConsoleColor.White; } Console.Write( "{0,-" + col2width + "}", ( i < col2lines.Count ? col2lines[i] : String.Empty ) ); Console.ResetColor( ); Console.WriteLine( ); } } // Code to detect redirection by Hans Passant on StackOverflow.com // http://stackoverflow.com/a/3453272 public static class ConsoleEx { public static bool OutputRedirected { get { return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdout ) ); } } public static bool InputRedirected { get { return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdin ) ); } } public static bool ErrorRedirected { get { return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stderr ) ); } } // P/Invoke: private enum FileType { Unknown, Disk, Char, Pipe }; private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 }; [DllImport( "kernel32.dll" )] private static extern FileType GetFileType( IntPtr hdl ); [DllImport( "kernel32.dll" )] private static extern IntPtr GetStdHandle( StdHandle std ); } } }