using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; namespace RobvanderWoude { class ListIntCmd { public static string progver = "1.07"; [STAThreadAttribute] static int Main( string[] args ) { #region Initialize variables int rc = 0; string separartor = Environment.NewLine; bool separatorset = false; bool copy = false; bool copyset = false; bool logging = false; bool logset = false; string logdir = Directory.GetParent( System.Reflection.Assembly.GetEntryAssembly( ).Location ).ToString( ); // This program's parent folder string logfile = Path.Combine( logdir, "ListIntCmd.log" ); bool logfileset = false; string logtext = String.Empty; DateTime logbegin; DateTime logend; #endregion Initialize variables #region Command Line Parsing if ( args.Length > 0 ) { foreach ( string arg in args ) { switch ( arg.Substring( 0, Math.Min( 2, arg.Length ) ).ToUpper( ) ) { case "/?": return ShowHelp( ); case "/C": if ( copyset ) { return ShowHelp( "Duplicate command line switch /C" ); } copy = true; copyset = true; break; case "/L": if ( logset ) { return ShowHelp( "Duplicate command line switch /L" ); } logging = true; logset = true; if ( arg.Length > 4 && arg[2] == ':' ) { logfile = Environment.ExpandEnvironmentVariables( arg.Substring( 3 ).Trim( "\" ".ToCharArray( ) ) ); logdir = Directory.GetParent( logfile ).ToString( ); logfileset = true; } break; default: if ( separatorset ) { return ShowHelp( ); } // Translate: \n to linefeed, \t to tab, \/ to slash, \\ to backslash, escaped \n to literal \n, escaped \t to literal \t separartor = arg.Replace( "\\n", Environment.NewLine ).Replace( "\\t", "\t" ).Replace( "\\/", "/" ).Replace( "\\\\", "\\" ).Replace( "\\\n", "\\n" ).Replace( "\\\t", "\\t" ); separatorset = true; break; } } } if ( logfileset && !String.IsNullOrEmpty( logfile ) ) { if ( !Directory.Exists( logdir ) ) { return ShowHelp( string.Format( "Invalid log path \"{0}\"", logdir ) ); } } #endregion Command Line Parsing try { string comspec = Environment.GetEnvironmentVariable( "COMSPEC" ); logbegin = DateTime.Now; logtext += string.Format( "ListIntCmd.exe, Version {0}{1}", progver, Environment.NewLine ); logtext += string.Format( "{0}{1}", Environment.OSVersion.VersionString, Environment.NewLine ); logtext += string.Format( "Search started at {0}{1}{1}", logbegin.ToString( "yyyy-MM-dd, HH:mm:ss.fff" ), Environment.NewLine ); logtext += string.Format( "COMSPEC=\"{0}, ProductVersion={1}\"{2}{2}", comspec, FileVersionInfo.GetVersionInfo( comspec ).ProductVersion, Environment.NewLine ); StreamReader file = new StreamReader( comspec, Encoding.ASCII ); string content = file.ReadToEnd( ); file.Close( ); string pattern = @"c\0m\0d\0\.\0e\0x\0e\0[\w\W]*?\(c\)"; if ( Regex.IsMatch( content, pattern ) ) { content = Regex.Match( content, pattern ).ToString( ); } List intcmds = new List( ) { "CD", "DATE", "GOTO", "KEYS", "REM", "TIME" }; // preload internal commands that are skipped by our previous -- too tight -- RegEx pattern logtext += string.Format( "{0}Preloaded internal commands:{0}{0}{1}{0}{0}", Environment.NewLine, string.Join( Environment.NewLine, intcmds.ToArray( ) ) ); // extended exclusion string for Windows 2000..10; the longer the exclusion string, the higher the risk that some new future internal command will be omited in the output string excludestr = "BAT,CMD,COM,DISABLEDELAYEDEXPANSION,DLL,EQU,EXE,GEQ,GTR,HH,JS,LEQ,LSS,MM,MSC,NEQ,NTDLL,SM,VBS,VERSION,VS,WS"; string[] excludearr = excludestr.Split( ",".ToCharArray( ) ); List exclude = new List( excludearr ); // Optimized for .NET Framework 2.0; in .NET Framework 3.5+ we might have used List exclude = excludestr.Split( ",".ToCharArray( ) ).ToList( ); pattern = @"([A-Z]\0){2,}"; Regex regex = new Regex( pattern ); if ( regex.IsMatch( content ) ) { logtext += string.Format( "{0}List of regex matches:{0}", Environment.NewLine ); foreach ( Match match in regex.Matches( content ) ) { string line = String.Empty; string intcmd = match.ToString( ).Replace( "\0", string.Empty ); line += string.Format( "{0}{1,-24}", Environment.NewLine, intcmd ); if ( exclude.Contains( intcmd ) ) { line += string.Format( "\texcluded by exlusion list", intcmd ); } else if ( intcmds.Contains( intcmd ) ) { line += string.Format( "\tskipped duplicate", intcmd ); } else { intcmds.Add( intcmd ); line += string.Format( "\tadded to the list of internal commands", intcmd ); } logtext += line.TrimEnd( ); } logtext += string.Format( "{0}{0}{0}Results so far:{0}{0}{1}{0}{0}", Environment.NewLine, String.Join( Environment.NewLine, intcmds.ToArray( ) ) ); intcmds.Sort( ); logtext += string.Format( "{0}Results after sorting:{0}{0}{1}{0}{0}", Environment.NewLine, String.Join( Environment.NewLine, intcmds.ToArray( ) ) ); } // Return a default list if we could not find the internal commands in %COMSPEC% if ( intcmds.Count == 0 ) { logtext += string.Format( "{0}Using default, hard-coded list{0}{0}", Environment.NewLine ); string defintcmdsstr = "ASSOC,BREAK,CALL,CD,CHDIR,CLS,COLOR,COPY,DATE,DEL,DIR,DPATH,ECHO,ENDLOCAL,ERASE,EXIT,FOR,FTYPE,GOTO,IF,KEYS,MD,MKDIR,MKLINK,MOVE,PATH,PAUSE,POPD,PROMPT,PUSHD,RD,REM,REN,RENAME,RMDIR,SET,SETLOCAL,SHIFT,START,TIME,TITLE,TYPE,VER,VERIFY,VOL"; string[] defintcmdsarr = defintcmdsstr.Split( ",".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ); intcmds = new List( defintcmdsarr ); // Optimized for .NET Framework 2.0; in .NET Framework 3.5+ we might have used List intcmds = defintcmdsstr.Split( ",".ToCharArray( ) ).ToList( ); rc = 2; } string result = String.Join( separartor, intcmds.ToArray( ) ); Console.Write( result ); if ( copy ) { logtext += string.Format( "Writing result to clipboard . . .{0}{0}", Environment.NewLine ); Clipboard.SetText( result ); logtext += string.Format( "Text written to clipboard:{1}{1}{0}{1}{1}", Clipboard.GetText( ), Environment.NewLine ); } if ( logging ) { logend = DateTime.Now; TimeSpan duration = logend - logbegin; logtext += string.Format( "Search ended at {0} ({1:N0} milliseconds){2}", logend.ToString( "yyyy-MM-dd, HH:mm:ss.fff" ), duration.TotalMilliseconds, Environment.NewLine ); StreamWriter logstream = new StreamWriter( logfile ); logstream.Write( logtext ); logstream.Close( ); } return rc; } catch ( Exception e ) { return ShowHelp( e.Message ); } } #region Error Handling public 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 #region Help Text /* ListIntCmd.exe, Version 1.07 List all available internal commands Usage: LISTINTCMD [ "separator" ] [ /C ] [ /L[:logfile] ] Where: separator is the character or string used to separate the command names in the output (default: linefeed) /C Copies output to clipboard /L[:logfile] Logs the entire search process to logfile (default log file name and location: ListIntCmd.log in program's parent folder) Notes: Use doublequotes if separator contains spaces or "special" characters. separator accepts \n for linefeeds, \t for tabs, \/ for slashes, \\ for backslashes, and """" for doublequotes. Return code 2 if commands could not be retrieved and default list had to be returned instead, 1 on other errors, 0 if all is well. Written by Rob van der Woude https://www.robvanderwoude.com */ #endregion Help Text #region Display Help Text Console.Error.WriteLine( ); Console.Error.WriteLine( "ListIntCmd.exe, Version {0}", progver ); Console.Error.WriteLine( "List all available internal commands" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "LISTINTCMD [ \"separator\" ] [ /C ] [ /L[:logfile] ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "separator" ); Console.ResetColor( ); Console.Error.WriteLine( " is the character or string used to separate the" ); Console.Error.WriteLine( " command names in the output (default: linefeed)" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /C C" ); Console.ResetColor( ); Console.Error.WriteLine( "opies output to clipboard" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /L[:logfile] L" ); Console.ResetColor( ); Console.Error.Write( "ogs the entire search process to " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "logfile" ); Console.ResetColor( ); Console.Error.WriteLine( " (default log file name and location:" ); Console.Error.WriteLine( " ListIntCmd.log in program's parent folder)" ); Console.Error.WriteLine( ); Console.Error.Write( "Notes: Use doublequotes if " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "separator" ); Console.ResetColor( ); Console.Error.WriteLine( " contains spaces or \"special\" characters." ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " separator" ); Console.ResetColor( ); Console.Error.Write( " accepts " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\\n" ); Console.ResetColor( ); Console.Error.Write( " for linefeeds, " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\\t" ); Console.ResetColor( ); Console.Error.Write( " for tabs, " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\\/" ); Console.ResetColor( ); Console.Error.WriteLine( " for slashes," ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " \\\\" ); Console.ResetColor( ); Console.Error.Write( " for backslashes, and " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "\"\"\"\"" ); Console.ResetColor( ); Console.Error.WriteLine( " for doublequotes." ); Console.Error.WriteLine( " Return code 2 if commands could not be retrieved and default list" ); Console.Error.WriteLine( " had to be returned instead, 1 on other errors, 0 if all is well." ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "https://www.robvanderwoude.com" ); #endregion Display Help Text return 1; } #endregion Error Handling } }