Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for rxgrep.cs

(view source code of rxgrep.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text.RegularExpressions;
  6.  
  7.  
  8. namespace RobvanderWoude
  9. {
  10. 	class RxGrep
  11. 	{
  12. 		static readonly string progver = "3.02";
  13.  
  14.  
  15. 		#region Global Variables
  16.  
  17. 		static bool dedup = false;
  18. 		static bool returngroup = false;
  19. 		static bool singlelinemode = false;
  20. 		static int skipmatches = 0;
  21. 		static int takematches = 0;
  22. 		static string groupseparator = " ";
  23. 		static List<int> groupnums = new List<int>( );
  24. 		static int bytes = -1;
  25. 		static List<string> dedupedmatches = new List<string>( );
  26.  
  27. 		#endregion Global Variables
  28.  
  29.  
  30. 		static int Main( string[] args )
  31. 		{
  32. 			#region Initialize Variables
  33.  
  34. 			bool caseset = false;
  35. 			bool quiet = false;
  36. 			bool skipset = false;
  37. 			bool takeset = false;
  38. 			string filename = string.Empty;
  39. 			string pattern;
  40. 			string input = string.Empty;
  41. 			int matchcount;
  42. 			int redirectnum = ( Console.IsInputRedirected ? 1 : 0 );
  43. 			RegexOptions regexoptions = RegexOptions.None;
  44.  
  45. 			#endregion Initialize Variables
  46.  
  47.  
  48. 			#region Command Line Parsing
  49.  
  50. 			if ( args.Length + redirectnum < 2 )
  51. 			{
  52. 				return ShowHelp( );
  53. 			}
  54.  
  55. 			List<string> arguments = new List<string>( args );
  56. 			if ( arguments.Contains( "/?" ) )
  57. 			{
  58. 				return ShowHelp( );
  59. 			}
  60.  
  61. 			if ( !Console.IsInputRedirected )
  62. 			{
  63. 				filename = arguments[0];
  64. 				arguments.RemoveAt( 0 );
  65. 			}
  66. 			pattern = arguments[0];
  67. 			arguments.RemoveAt( 0 );
  68.  
  69. 			foreach ( string option in arguments )
  70. 			{
  71. 				switch ( option.ToUpper( ).Substring( 0, 2 ) )
  72. 				{
  73. 					case "/?":
  74. 						return ShowHelp( );
  75. 					case "/A":
  76. 						if ( groupseparator == "\t" )
  77. 						{
  78. 							return ShowHelp( "Duplicate switch /A" );
  79. 						}
  80. 						groupseparator = "\t";
  81. 						break;
  82. 					case "/D":
  83. 						if ( dedup )
  84. 						{
  85. 							return ShowHelp( "Duplicate switch /D" );
  86. 						}
  87. 						dedup = true;
  88. 						break;
  89. 					case "/F":
  90. 						if ( bytes != -1 )
  91. 						{
  92. 							return ShowHelp( "Duplicate switch /F" );
  93. 						}
  94. 						try
  95. 						{
  96. 							bytes = Convert.ToInt32( option.Substring( 3 ) );
  97. 						}
  98. 						catch ( Exception e )
  99. 						{
  100. 							Console.Error.WriteLine( "Error: {0}", e.Message );
  101. 							return ShowHelp( string.Format( "Invalid command line switch \"{0}\"", option ) );
  102. 						}
  103. 						break;
  104. 					case "/G":
  105. 						returngroup = true;
  106. 						int groupnum = 0;
  107. 						try
  108. 						{
  109. 							groupnum = Convert.ToInt32( option.Substring( 3 ) );
  110. 							if ( groupnum < 1 )
  111. 							{
  112. 								return ShowHelp( "Invalid group number {0} specified", groupnum.ToString( ) );
  113. 							}
  114. 						}
  115. 						catch ( Exception e )
  116. 						{
  117. 							Console.Error.WriteLine( "Error: {0}", e.Message );
  118. 							return ShowHelp( string.Format( "Invalid command line switch \"{0}\"", option ) );
  119. 						}
  120. 						if ( groupnum > 0 )
  121. 						{
  122. 							groupnums.Add( groupnum );
  123. 						}
  124. 						break;
  125. 					case "/I":
  126. 						if ( caseset )
  127. 						{
  128. 							return ShowHelp( "Duplicate switch /L" );
  129. 						}
  130. 						regexoptions |= RegexOptions.IgnoreCase;
  131. 						caseset = true;
  132. 						break;
  133. 					case "/L":
  134. 						if ( singlelinemode )
  135. 						{
  136. 							return ShowHelp( "Duplicate switch /I" );
  137. 						}
  138. 						singlelinemode = true;
  139. 						break;
  140. 					case "/Q":
  141. 						if ( quiet )
  142. 						{
  143. 							return ShowHelp( "Duplicate switch /Q" );
  144. 						}
  145. 						quiet = true;
  146. 						break;
  147. 					case "/S":
  148. 						if ( skipset )
  149. 						{
  150. 							return ShowHelp( "Duplicate switch /S" );
  151. 						}
  152. 						try
  153. 						{
  154. 							skipmatches = Convert.ToInt32( option.Substring( 3 ) );
  155. 						}
  156. 						catch ( Exception e )
  157. 						{
  158. 							Console.Error.WriteLine( "Error: {0}", e.Message );
  159. 							return ShowHelp( string.Format( "Invalid command line switch \"{0}\"", option ) );
  160. 						}
  161. 						break;
  162. 					case "/T":
  163. 						if ( takeset )
  164. 						{
  165. 							return ShowHelp( "Duplicate switch /T" );
  166. 						}
  167. 						try
  168. 						{
  169. 							takematches = Convert.ToInt32( option.Substring( 3 ) );
  170. 						}
  171. 						catch ( Exception e )
  172. 						{
  173. 							Console.Error.WriteLine( "Error: {0}", e.Message );
  174. 							return ShowHelp( string.Format( "Invalid command line switch \"{0}\"", option ) );
  175. 						}
  176. 						break;
  177. 					default:
  178. 						return ShowHelp( string.Format( "Invalid command line {0}: \"{1}\"", ( option[0] == '/' ? "switch" : "argument" ), option ) );
  179. 				}
  180. 			}
  181.  
  182. 			#endregion Command Line Parsing
  183.  
  184.  
  185. 			#region Command Line Arguments Validation
  186.  
  187. 			if ( Console.IsInputRedirected )
  188. 			{
  189. 				// Read the redirected Standard Input
  190. 				input = Console.In.ReadToEnd( );
  191. 				if ( bytes != -1 )
  192. 				{
  193. 					input = input.Substring( 0, Math.Min( bytes, input.Length ) );
  194. 				}
  195. 			}
  196. 			else
  197. 			{
  198. 				// Check if the file name is valid
  199. 				if ( filename.IndexOf( "/" ) > -1 )
  200. 				{
  201. 					return ShowHelp( );
  202. 				}
  203. 				if ( filename.IndexOfAny( "?*".ToCharArray( ) ) > -1 )
  204. 				{
  205. 					return ShowHelp( "Wildcards not allowed" );
  206. 				}
  207. 				// Check if the file exists
  208. 				if ( File.Exists( filename ) )
  209. 				{
  210. 					// Read the file content
  211. 					using ( StreamReader file = new StreamReader( filename ) )
  212. 					{
  213. 						if ( bytes == -1 )
  214. 						{
  215. 							input = file.ReadToEnd( );
  216. 						}
  217. 						else
  218. 						{
  219. 							char[] buffer = new char[bytes];
  220. 							file.Read( buffer, 0, bytes );
  221. 							input = string.Join( string.Empty, buffer );
  222. 						}
  223. 					}
  224. 				}
  225. 				else
  226. 				{
  227. 					return ShowHelp( string.Format( "File not found: \"{0}\"", filename ) );
  228. 				}
  229. 			}
  230.  
  231. 			if ( dedup && ( skipset || takeset ) )
  232. 			{
  233. 				return ShowHelp( "Switch /D cannot be combined with switches /S or /T" );
  234. 			}
  235.  
  236. 			#endregion Command Line Arguments Validation
  237.  
  238.  
  239. 			// Now that the command line parsing is finally done, let's get some action
  240. 			if ( singlelinemode )
  241. 			{
  242. 				matchcount = 0;
  243. 				foreach ( string line in input.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries ) )
  244. 				{
  245. 					matchcount += DisplayMatches( line, pattern, regexoptions );
  246. 				}
  247.             }
  248. 			else
  249. 			{
  250. 				matchcount = DisplayMatches( input, pattern, regexoptions );
  251. 			}
  252. 			return matchcount;
  253. 		}
  254.  
  255.  
  256. 		// The main functionality: display all matching substrings
  257. 		public static int DisplayMatches( string haystack, string needle, RegexOptions options )
  258. 		{
  259. 			int counter = 0;
  260. 			int displayed = 0;
  261. 			// Get all matches
  262. 			MatchCollection matches = Regex.Matches( haystack, needle, options );
  263. 			if ( dedup )
  264. 			{
  265. 				//List<string> dedupedmatches = new List<string>( );
  266. 				foreach ( Match match in matches )
  267. 				{
  268. 					if ( returngroup )
  269. 					{
  270. 						if ( match.Groups.Count >= groupnums.Count )
  271. 						{
  272. 							bool empty = true;
  273. 							foreach ( int groupnum in groupnums )
  274. 							{
  275. 								Group group = match.Groups[groupnum];
  276. 								if ( !dedupedmatches.Contains( group.Value ) )
  277. 								{
  278. 									if ( empty )
  279. 									{
  280. 										Console.Write( group.Value );
  281. 									}
  282. 									else
  283. 									{
  284. 										Console.Write( groupseparator + group.Value );
  285. 									}
  286. 									dedupedmatches.Add( group.Value );
  287. 									displayed += 1;
  288. 									empty = false;
  289. 								}
  290. 							}
  291. 							Console.WriteLine( );
  292. 						}
  293. 					}
  294. 					else if ( !dedupedmatches.Contains( match.Value ) )
  295. 					{
  296. 						Console.WriteLine( match.Value );
  297. 						dedupedmatches.Add( match.Value );
  298. 						displayed += 1;
  299. 					}
  300. 				}
  301. 			}
  302. 			else
  303. 			{
  304. 				if ( matches.Count > skipmatches )
  305. 				{
  306. 					foreach ( Match match in matches )
  307. 					{
  308. 						if ( counter >= skipmatches && ( displayed < takematches || takematches == 0 ) )
  309. 						{
  310. 							if ( returngroup && match.Groups.Count >= groupnums.Count )
  311. 							{
  312. 								bool empty = true;
  313. 								foreach ( int groupnum in groupnums )
  314. 								{
  315. 									Group group = match.Groups[groupnum];
  316. 									if ( empty )
  317. 									{
  318. 										Console.Write( group.Value );
  319. 									}
  320. 									else
  321. 									{
  322. 										Console.Write( groupseparator + group.Value );
  323. 									}
  324. 									displayed += 1;
  325. 									empty = false;
  326. 								}
  327. 								Console.WriteLine( );
  328. 							}
  329. 							else
  330. 							{
  331. 								Console.WriteLine( match.Value );
  332. 								displayed += 1;
  333. 							}
  334. 						}
  335. 						counter += 1;
  336. 					}
  337. 				}
  338. 			}
  339. 			return displayed;
  340. 		}
  341.  
  342.  
  343. 		#region Error Handling
  344.  
  345. 		public static int ShowHelp( params string[] errmsg )
  346. 		{
  347. 			#region Error Message
  348.  
  349. 			if ( errmsg.Length > 0 )
  350.  
  351. 			{
  352. 				List<string> errargs = new List<string>( errmsg );
  353. 				errargs.RemoveAt( 0 );
  354. 				Console.Error.WriteLine( );
  355. 				Console.ForegroundColor = ConsoleColor.Red;
  356. 				Console.Error.Write( "ERROR:\t" );
  357. 				Console.ForegroundColor = ConsoleColor.White;
  358. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  359. 				Console.ResetColor( );
  360. 			}
  361.  
  362. 			#endregion Error Message
  363.  
  364.  
  365. 			#region Help Text
  366.  
  367. 			/*
  368. 			RxGrep,  Version 3.00
  369. 			Multi-line FindStr/Grep like tool
  370.  
  371. 			Usage:   RXGREP  filename  pattern  [ options ]
  372. 			or:      command  |  RXGREP  pattern  [ options ]
  373.  
  374. 			Where:   filename   is the file to be filtered
  375. 			         command    is the command whose standard output is to be filtered
  376. 			         pattern    is the search pattern (regular expression)
  377.  
  378. 			Options: /A         use tAb as separator for multiple groups
  379. 			                    (default: space)
  380. 			         /D         do not show Duplicate matches
  381. 			         /F:nn      search only the First nn bytes
  382. 			         /G:nn      return match Group #nn (may be used multiple times)
  383. 			         /I         case Insensitive search
  384. 			         /L         single Line mode: ^ and $ match begin and end of each line
  385. 			         /Q         Quiet mode: no message if no match is found
  386. 			         /S:nn      Skip the first nn matches
  387. 			         /T:nn      Take only nn matches
  388.  
  389. 			Example: ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |
  390. 			         RXGREP "\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+"
  391. 			         (to be read as a single command line) will return something like:
  392. 			                         125    D:\sourcedir\subdir\
  393. 			            New File                 342        brandnewfile.ext
  394. 			            Newer                  4.06m        updatedfile.ext
  395. 			          *EXTRA File              2.40m        deletedfile.ext
  396.  
  397. 			Notes:   If /F:nn is used and a file is specified, only the first nn bytes
  398. 			         of that file will be read; if the input is redirected, it is read
  399. 			         entirely, and then chopped to nn bytes before being searched.
  400. 			         /G:nn can be used multiple times; all matching groups are written
  401. 			         to screen, separated by spaces, unless /A is used, in which case
  402. 			         the matches will be separated by tabs; matching groups are shown
  403. 			         in order of input, not in order of command line arguments, e.g.
  404. 			         /G:1 /G:3 will show the same result as /G:3 /G:1.
  405. 			         Switches /D and /G cannot be combined with /S or /T.
  406. 			         Return code ("errorlevel") will equal the number of matches found,
  407. 			         or -1 in case of (command line) errors.
  408.  
  409. 			Written by Rob van der Woude
  410. 			https://www.robvanderwoude.com
  411. 			 */
  412.  
  413. 			#endregion Help Text
  414.  
  415.  
  416. 			#region Display Help Text
  417.  
  418. 			Console.Error.WriteLine( );
  419. 			Console.Error.WriteLine( "RxGrep,  Version {0}", progver );
  420. 			Console.Error.WriteLine( "Multi-line FindStr/Grep like tool" );
  421. 			Console.Error.WriteLine( );
  422.  
  423. 			Console.Error.Write( "Usage:   " );
  424. 			Console.ForegroundColor = ConsoleColor.White;
  425. 			Console.Error.WriteLine( "RXGREP  filename  pattern  [ options ]" );
  426. 			Console.ResetColor( );
  427.  
  428. 			Console.Error.Write( "or:      " );
  429. 			Console.ForegroundColor = ConsoleColor.White;
  430. 			Console.Error.WriteLine( "command | RXGREP  pattern  [ options ]" );
  431. 			Console.ResetColor( );
  432.  
  433. 			Console.Error.WriteLine( );
  434.  
  435. 			Console.Error.Write( "Where:   " );
  436. 			Console.ForegroundColor = ConsoleColor.White;
  437. 			Console.Error.Write( "filename" );
  438. 			Console.ResetColor( );
  439. 			Console.Error.WriteLine( "   is the file to be filtered" );
  440.  
  441. 			Console.ForegroundColor = ConsoleColor.White;
  442. 			Console.Error.Write( "         command" );
  443. 			Console.ResetColor( );
  444. 			Console.Error.WriteLine( "    is the command whose standard output is to be filtered" );
  445.  
  446. 			Console.ForegroundColor = ConsoleColor.White;
  447. 			Console.Error.Write( "         pattern" );
  448. 			Console.ResetColor( );
  449. 			Console.Error.WriteLine( "    is the search pattern (regular expression)" );
  450.  
  451. 			Console.Error.WriteLine( );
  452.  
  453. 			Console.Error.Write( "Options: " );
  454. 			Console.ForegroundColor = ConsoleColor.White;
  455. 			Console.Error.Write( "/A" );
  456. 			Console.ResetColor( );
  457. 			Console.Error.Write( "         use t" );
  458. 			Console.ForegroundColor = ConsoleColor.White;
  459. 			Console.Error.Write( "A" );
  460. 			Console.ResetColor( );
  461. 			Console.Error.WriteLine( "b as separator for multiple groups" );
  462.  
  463. 			Console.Error.WriteLine( "                    (default: space)" );
  464.  
  465. 			Console.ForegroundColor = ConsoleColor.White;
  466. 			Console.Error.Write( "         /D" );
  467. 			Console.ResetColor( );
  468. 			Console.Error.Write( "         do not show " );
  469. 			Console.ForegroundColor = ConsoleColor.White;
  470. 			Console.Error.Write( "D" );
  471. 			Console.ResetColor( );
  472. 			Console.Error.WriteLine( "uplicate matches" );
  473.  
  474. 			Console.ForegroundColor = ConsoleColor.White;
  475. 			Console.Error.Write( "         /F:nn" );
  476. 			Console.ResetColor( );
  477. 			Console.Error.Write( "      search only the " );
  478. 			Console.ForegroundColor = ConsoleColor.White;
  479. 			Console.Error.Write( "F" );
  480. 			Console.ResetColor( );
  481. 			Console.Error.Write( "irst " );
  482. 			Console.ForegroundColor = ConsoleColor.White;
  483. 			Console.Error.Write( "nn" );
  484. 			Console.ResetColor( );
  485. 			Console.Error.WriteLine( " bytes" );
  486.  
  487. 			Console.ForegroundColor = ConsoleColor.White;
  488. 			Console.Error.Write( "         /G:nn" );
  489. 			Console.ResetColor( );
  490. 			Console.Error.Write( "      return match " );
  491. 			Console.ForegroundColor = ConsoleColor .White;
  492. 			Console.Error.Write( "G" );
  493. 			Console.ResetColor( );
  494. 			Console.Error.Write( "roup " );
  495. 			Console.ForegroundColor = ConsoleColor.White;
  496. 			Console.Error.WriteLine( "#nn" );
  497. 			Console.ResetColor( );
  498.  
  499. 			Console.ForegroundColor = ConsoleColor.White;
  500. 			Console.Error.Write( "         /I" );
  501. 			Console.ResetColor( );
  502. 			Console.Error.Write( "         case " );
  503. 			Console.ForegroundColor = ConsoleColor.White;
  504. 			Console.Error.Write( "I" );
  505. 			Console.ResetColor( );
  506. 			Console.Error.WriteLine( "nsensitive search" );
  507.  
  508. 			Console.ForegroundColor = ConsoleColor.White;
  509. 			Console.Error.Write( "         /L" );
  510. 			Console.ResetColor( );
  511. 			Console.Error.Write( "         single " );
  512. 			Console.ForegroundColor = ConsoleColor.White;
  513. 			Console.Error.Write( "L" );
  514. 			Console.ResetColor( );
  515. 			Console.Error.WriteLine( "ine mode: ^ and $ match begin and end of each line" );
  516.  
  517. 			Console.ForegroundColor = ConsoleColor.White;
  518. 			Console.Error.Write( "         /Q         Q" );
  519. 			Console.ResetColor( );
  520. 			Console.Error.WriteLine( "uiet mode: no message if no match is found" );
  521.  
  522. 			Console.ForegroundColor = ConsoleColor.White;
  523. 			Console.Error.Write( "         /S:nn      S" );
  524. 			Console.ResetColor( );
  525. 			Console.Error.Write( "kip the first " );
  526. 			Console.ForegroundColor = ConsoleColor.White;
  527. 			Console.Error.Write( "nn" );
  528. 			Console.ResetColor( );
  529. 			Console.Error.WriteLine( " matches" );
  530.  
  531. 			Console.ForegroundColor = ConsoleColor.White;
  532. 			Console.Error.Write( "         /T:nn      T" );
  533. 			Console.ResetColor( );
  534. 			Console.Error.Write( "ake only " );
  535. 			Console.ForegroundColor = ConsoleColor.White;
  536. 			Console.Error.Write( "nn" );
  537. 			Console.ResetColor( );
  538. 			Console.Error.WriteLine( " matches" );
  539.  
  540. 			Console.Error.WriteLine( );
  541.  
  542. 			Console.Error.Write( "Example: " );
  543. 			Console.ForegroundColor = ConsoleColor.White;
  544. 			Console.Error.WriteLine( @"ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |" );
  545.  
  546. 			Console.Error.WriteLine( @"         RXGREP ""\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+""" );
  547. 			Console.ResetColor( );
  548.  
  549. 			Console.Error.WriteLine( "         (to be read as a single command line) will return something like:" );
  550.  
  551. 			Console.ForegroundColor = ConsoleColor.White;
  552. 			Console.Error.WriteLine( @"                         125    D:\sourcedir\subdir\" );
  553.  
  554. 			Console.Error.WriteLine( "            New File                 342        brandnewfile.ext" );
  555.  
  556. 			Console.Error.WriteLine( "            Newer                  4.06m        updatedfile.ext" );
  557.  
  558. 			Console.Error.WriteLine( "          *EXTRA File              2.40m        deletedfile.ext" );
  559. 			Console.ResetColor( );
  560.  
  561. 			Console.Error.WriteLine( );
  562.  
  563. 			Console.Error.Write( "Notes:   If " );
  564. 			Console.ForegroundColor = ConsoleColor.White;
  565. 			Console.Error.Write( "/F:nn" );
  566. 			Console.ResetColor( );
  567. 			Console.Error.Write( " is used and a file is specified, only the first " );
  568. 			Console.ForegroundColor = ConsoleColor.White;
  569. 			Console.Error.Write( "nn" );
  570. 			Console.ResetColor( );
  571. 			Console.Error.WriteLine( " bytes" );
  572.  
  573. 			Console.Error.WriteLine( "         of that file will be read; if the input is redirected, it is read" );
  574.  
  575. 			Console.Error.Write( "         entirely, and then chopped to " );
  576. 			Console.ForegroundColor = ConsoleColor.White;
  577. 			Console.Error.Write( "nn" );
  578. 			Console.ResetColor( );
  579. 			Console.Error.WriteLine( " bytes before being searched." );
  580.  
  581.  
  582. 			Console.ForegroundColor = ConsoleColor.White;
  583. 			Console.Error.Write( "         /G:nn" );
  584. 			Console.ResetColor( );
  585. 			Console.Error.WriteLine( " can be used multiple times; all matching groups are written" );
  586.  
  587. 			Console.Error.Write( "         to screen, separated by spaces, unless " );
  588. 			Console.ForegroundColor = ConsoleColor.White;
  589. 			Console.Error.Write( "/A" );
  590. 			Console.ResetColor( );
  591. 			Console.Error.WriteLine( " is used, in which case" );
  592.  
  593.  
  594. 			Console.Error.WriteLine( "         the matches will be separated by tabs; matching groups are shown" );
  595.  
  596. 			Console.Error.WriteLine( "         in order of input, not in order of command line arguments, e.g." );
  597.  
  598. 			Console.ForegroundColor = ConsoleColor.White;
  599. 			Console.Error.Write( "         /G:1 /G:3" );
  600. 			Console.ResetColor( );
  601. 			Console.Error.Write( " will show the same result as " );
  602. 			Console.ForegroundColor = ConsoleColor.White;
  603. 			Console.Error.Write( "/G:3 /G:1" );
  604. 			Console.ResetColor( );
  605. 			Console.Error.WriteLine( "." );
  606.  
  607. 			Console.Error.Write( "         Switches " );
  608. 			Console.ForegroundColor = ConsoleColor.White;
  609. 			Console.Error.Write( "/D" );
  610. 			Console.ResetColor( );
  611. 			Console.Error.Write( " and " );
  612. 			Console.ForegroundColor = ConsoleColor.White;
  613. 			Console.Error.Write( "/G" );
  614. 			Console.ResetColor( );
  615. 			Console.Error.Write( " cannot be combined with " );
  616. 			Console.ForegroundColor = ConsoleColor.White;
  617. 			Console.Error.Write( "/S" );
  618. 			Console.ResetColor( );
  619. 			Console.Error.Write( " or " );
  620. 			Console.ForegroundColor = ConsoleColor.White;
  621. 			Console.Error.Write( "/T" );
  622. 			Console.ResetColor( );
  623. 			Console.Error.WriteLine( "." );
  624.  
  625. 			Console.Error.WriteLine( "         Return code (\"errorlevel\") will equal the number of matches found," );
  626.  
  627. 			Console.Error.WriteLine( "         or -1 in case of (command line) errors." );
  628.  
  629. 			Console.Error.WriteLine( );
  630.  
  631. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  632.  
  633. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  634.  
  635. 			#endregion Display Help Text
  636.  
  637.  
  638. 			return -1;
  639. 		}
  640.  
  641. 		#endregion Error Handling
  642. 	}
  643. }

page last modified: 2024-04-16; loaded in 0.0100 seconds