Powered by GeSHi

Source code for which.cs

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

  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Text.RegularExpressions;
  5.  
  6. namespace RobvanderWoude
  7. {
  8. 	class Which
  9. 	{
  10. 		static int Main( string[] args )
  11. 		{
  12. 			string[] internals = "APPEND ASSOC BREAK CALL CD CHCP 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 TRUENAME TYPE VER VERIFY VOL".Split( ' ' );
  13. 			string[] path = ( Environment.CurrentDirectory + ";" + Environment.GetEnvironmentVariable( "PATH" ) ).Split( ';' );
  14. 			string[] pathext = ( ";" + Environment.GetEnvironmentVariable( "PATHEXT" ).ToLower( ) ).Split( ';' );
  15. 			bool all = false;
  16. 			bool extonly = false;
  17. 			string prog = string.Empty;
  18. 			bool set_all = false;
  19. 			bool set_prog = false;
  20. 			bool set_ext = false;
  21. 			bool found = false;
  22.  
  23. 			#region Command Line Parsing
  24.  
  25. 			if ( args.Length == 0 )
  26. 			{
  27. 				return WriteError( );
  28. 			}
  29.  
  30. 			foreach ( string arg in args )
  31. 			{
  32. 				if ( arg[0] == '/' )
  33. 				{
  34. 					if ( arg.ToUpper( ) == "/A" )
  35. 					{
  36. 						if ( set_all )
  37. 						{
  38. 							return WriteError( "Duplicate command line switch: " + arg );
  39. 						}
  40. 						else
  41. 						{
  42. 							all = true;
  43. 							set_all = true;
  44. 						}
  45. 					}
  46. 					else
  47. 						if ( arg.ToUpper( ) == "/X" )
  48. 						{
  49. 							if ( set_ext )
  50. 							{
  51. 								return WriteError( "Duplicate command line switch: " + arg );
  52. 							}
  53. 							else
  54. 							{
  55. 								extonly = true;
  56. 								set_ext = true;
  57. 							}
  58. 						}
  59. 						else
  60. 						{
  61. 							if ( arg == "/?" )
  62. 							{
  63. 								return WriteError( );
  64. 							}
  65. 							else
  66. 							{
  67. 								return WriteError( "Invalid command line switch: " + arg );
  68. 							}
  69. 						}
  70. 				}
  71. 				else
  72. 				{
  73. 					if ( set_prog )
  74. 					{
  75. 						return WriteError( "Invalid or duplicate command line argument: " + arg );
  76. 					}
  77. 					else
  78. 					{
  79. 						char[] forbidden = { '\\', '?', '*', ':', ';', '/' };
  80. 						if ( arg.IndexOfAny( forbidden ) == -1 )
  81. 						{
  82. 							prog = arg;
  83. 							set_prog = true;
  84. 						}
  85. 						else
  86. 						{
  87. 							return WriteError( "Invalid characters in specified program name: " + arg );
  88. 						}
  89. 					}
  90. 				}
  91. 			}
  92.  
  93. 			#endregion Command Line Parsing
  94.  
  95. 			try
  96. 			{
  97. 				if ( !extonly )
  98. 				{
  99. 					// Try DOSKEY macros first
  100. 					Process doskey = new Process( );
  101. 					doskey.StartInfo.Arguments = "/macros";
  102. 					doskey.StartInfo.CreateNoWindow = false;
  103. 					doskey.StartInfo.FileName = Environment.GetFolderPath( Environment.SpecialFolder.System ) + "\\doskey.exe";
  104. 					doskey.StartInfo.LoadUserProfile = false;
  105. 					doskey.StartInfo.RedirectStandardError = false;
  106. 					doskey.StartInfo.RedirectStandardInput = false;
  107. 					doskey.StartInfo.RedirectStandardOutput = true;
  108. 					doskey.StartInfo.UseShellExecute = false;
  109. 					doskey.Start( );
  110. 					doskey.WaitForExit( 1000 );
  111. 					do
  112. 					{
  113. 						string line = doskey.StandardOutput.ReadLine( );
  114. 						if ( !found || all )
  115. 						{
  116. 							if ( !string.IsNullOrWhiteSpace( line ) )
  117. 							{
  118. 								if ( line.IndexOf( '=' ) > 0 )
  119. 								{
  120. 									string pattern = "^" + prog.ToUpper( ).Replace( ".", "\\." ) + "=";
  121. 									if ( Regex.IsMatch( line.ToUpper( ), pattern ) )
  122. 									{
  123. 										Console.ForegroundColor = ConsoleColor.White;
  124. 										Console.Write( "[{0}]::", doskey.StartInfo.FileName.ToUpper( ) );
  125. 										Console.ResetColor( );
  126. 										Console.WriteLine( line );
  127. 										found = true;
  128. 									}
  129. 								}
  130. 							}
  131. 						}
  132. 					} while ( doskey.StandardOutput.Peek( ) != -1 );
  133. 					doskey.Close( );
  134.  
  135. 					// Next try internal commands
  136. 					if ( !found || all )
  137. 					{
  138. 						if ( prog.IndexOf( '.' ) == -1 )
  139. 						{
  140. 							foreach ( string intern in internals )
  141. 							{
  142. 								if ( intern == prog.ToUpper( ) )
  143. 								{
  144. 									Console.ForegroundColor = ConsoleColor.White;
  145. 									Console.Write( "[{0}]::", Environment.GetEnvironmentVariable( "COMSPEC" ).ToUpper( ) );
  146. 									Console.ResetColor( );
  147. 									Console.WriteLine( prog.ToUpper( ) );
  148. 									found = true;
  149. 								}
  150. 							}
  151. 						}
  152. 					}
  153. 				}
  154.  
  155. 				// Finally try external commands
  156. 				if ( !found || all )
  157. 				{
  158. 					foreach ( string folder in path )
  159. 					{
  160. 						if ( !found || all )
  161. 						{
  162. 							if ( !string.IsNullOrWhiteSpace( folder ) )
  163. 							{
  164. 								string dir = ( folder + "\\" ).Replace( "\\\\", "\\" );
  165. 								foreach ( string ext in pathext )
  166. 								{
  167. 									if ( !found || all )
  168. 									{
  169. 										// The EXTERNAL program FILE to be searched MUST have an extension, either
  170. 										// specified on the command line or one of the extensions listed in PATHEXT.
  171. 										if ( ( prog + ext ).IndexOf( '.' ) > -1 )
  172. 										{
  173. 											if ( File.Exists( dir + prog + ext ) )
  174. 											{
  175. 												Console.WriteLine( dir + prog + ext );
  176. 												found = true;
  177. 											}
  178. 										}
  179. 									}
  180. 								}
  181. 							}
  182. 						}
  183. 					}
  184. 				}
  185.  
  186. 				if ( found )
  187. 				{
  188. 					return 0;
  189. 				}
  190. 				else
  191. 				{
  192. 					return 1;
  193. 				}
  194. 			}
  195. 			catch ( Exception e )
  196. 			{
  197. 				return WriteError( e.Message );
  198. 			}
  199. 		}
  200.  
  201.  
  202. 		#region Error Handling
  203.  
  204. 		public static int WriteError( Exception e = null )
  205. 		{
  206. 			return WriteError( e == null ? null : e.Message );
  207. 		}
  208.  
  209. 		public static int WriteError( string errorMessage )
  210. 		{
  211. 			if ( string.IsNullOrEmpty( errorMessage ) == false )
  212. 			{
  213. 				Console.Error.WriteLine( );
  214. 				Console.ForegroundColor = ConsoleColor.Red;
  215. 				Console.Error.Write( "ERROR: " );
  216. 				Console.ForegroundColor = ConsoleColor.White;
  217. 				Console.Error.WriteLine( errorMessage );
  218. 				Console.ResetColor( );
  219. 			}
  220.  
  221. 			/*
  222. 			Which,  Version 1.30
  223. 			Port of the UNIX command to Windows
  224.  
  225. 			Usage:   WHICH  progname  [ /A ]  [ /X ]
  226.  
  227. 			Where:   progname   the program name or internal command to be searched for
  228. 			         /A         returns All matches (default: stop at first match)
  229. 			         /X         returns eXternal commands only, no DOSKEY macros or
  230. 			                    internal commands   (default: all types)
  231.  
  232. 			Note:    By default, this program first compares the specified name against
  233. 			         a list of active DOSKEY macros, next against a (hard-coded) list
  234. 			         of CMD's internal commands, and finally it tries to find a matching
  235. 			         program file in the current directory and the PATH, using the
  236. 			         extensions listed in PATHEXT.
  237.  
  238. 			Written by Rob van der Woude
  239. 			http://www.robvanderwoude.com
  240. 			*/
  241.  
  242. 			Console.Error.WriteLine( );
  243. 			Console.Error.WriteLine( "Which,  Version 1.30" );
  244. 			Console.Error.WriteLine( "Port of the UNIX command to Windows" );
  245. 			Console.Error.WriteLine( );
  246. 			Console.Error.Write( "Usage:   " );
  247. 			Console.ForegroundColor = ConsoleColor.White;
  248. 			Console.Error.WriteLine( "WHICH  progname  [ /A ]  [ /X ]" );
  249. 			Console.ResetColor( );
  250. 			Console.Error.WriteLine( );
  251. 			Console.Error.Write( "Where:   " );
  252. 			Console.ForegroundColor = ConsoleColor.White;
  253. 			Console.Error.Write( "progname" );
  254. 			Console.ResetColor( );
  255. 			Console.Error.WriteLine( "   the program name or internal command to be searched for" );
  256. 			Console.ForegroundColor = ConsoleColor.White;
  257. 			Console.Error.Write( "         /A" );
  258. 			Console.ResetColor( );
  259. 			Console.Error.Write( "         returns " );
  260. 			Console.ForegroundColor = ConsoleColor.White;
  261. 			Console.Error.Write( "A" );
  262. 			Console.ResetColor( );
  263. 			Console.Error.WriteLine( "ll matches      (default: stop at first match)" );
  264. 			Console.ForegroundColor = ConsoleColor.White;
  265. 			Console.Error.Write( "         /X" );
  266. 			Console.ResetColor( );
  267. 			Console.Error.Write( "         returns e" );
  268. 			Console.ForegroundColor = ConsoleColor.White;
  269. 			Console.Error.Write( "X" );
  270. 			Console.ResetColor( );
  271. 			Console.Error.WriteLine( "ternal commands only, no DOSKEY macros or" );
  272. 			Console.Error.WriteLine( "                    internal commands        (default: all types)" );
  273. 			Console.Error.WriteLine( );
  274. 			Console.Error.WriteLine( "Note:    By default, this program first compares the specified name against" );
  275. 			Console.Error.WriteLine( "         a list of active DOSKEY macros, next against a (hard-coded) list" );
  276. 			Console.Error.WriteLine( "         of CMD's internal commands, and finally it tries to find a matching" );
  277. 			Console.Error.WriteLine( "         program file in the current directory and the PATH, using the" );
  278. 			Console.Error.WriteLine( "         extensions listed in PATHEXT." );
  279. 			Console.Error.WriteLine( );
  280. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  281. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  282. 			return 1;
  283. 		}
  284.  
  285. 		#endregion
  286. 	}
  287. }
  288.