Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for checkvarsvbs.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6.  
  7.  
  8. namespace RobvanderWoude
  9. {
  10. 	class CheckVarsVBS
  11. 	{
  12. 		static string progver = "1.00";
  13.  
  14.  
  15. 		static int Main( string[] args )
  16. 		{
  17. 			#region Initialize Variables
  18.  
  19. 			int rc = 0;
  20. 			SortedList<string, int> subroutines = new SortedList<string, int>( );
  21. 			SortedList<string, int> variables = new SortedList<string, int>( );
  22. 			bool showsubs = true;
  23. 			bool showvars = true;
  24. 			bool unusedonly = false;
  25. 			string scriptfile = String.Empty;
  26. 			string scriptcode = String.Empty;
  27. 			int columnwidth = 12;
  28.  
  29. 			#endregion Initialize Variables
  30.  
  31.  
  32. 			#region Command Line Parsing
  33.  
  34. 			if ( args.Length == 0 )
  35. 			{
  36. 				return ShowHelp( );
  37. 			}
  38.  
  39. 			foreach ( string arg in args )
  40. 			{
  41. 				if ( arg[0] == '/' )
  42. 				{
  43. 					if ( arg.ToUpper( ) == "/?" )
  44. 					{
  45. 						return ShowHelp( );
  46. 					}
  47. 					else if ( arg.ToUpper( ) == "/S" )
  48. 					{
  49. 						if ( !showvars )
  50. 						{
  51. 							return ShowHelp( "Duplicate command line switch /S" );
  52. 						}
  53. 						if ( !showsubs )
  54. 						{
  55. 							return ShowHelp( "Use /S or /V or neither, but not both" );
  56. 						}
  57. 						showvars = false;
  58. 					}
  59. 					else if ( arg.ToUpper( ) == "/U" )
  60. 					{
  61. 						if ( unusedonly )
  62. 						{
  63. 							return ShowHelp( "Duplicate command line switch /U" );
  64. 						}
  65. 						unusedonly = true;
  66. 					}
  67. 					else if ( arg.ToUpper( ) == "/V" )
  68. 					{
  69. 						if ( !showsubs )
  70. 						{
  71. 							return ShowHelp( "Duplicate command line switch /V" );
  72. 						}
  73. 						if ( !showvars )
  74. 						{
  75. 							return ShowHelp( "Use /S or /V or neither, but not both" );
  76. 						}
  77. 						showsubs = false;
  78. 					}
  79. 					else
  80. 					{
  81. 						return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  82. 					}
  83. 				}
  84. 				else
  85. 				{
  86. 					if ( !String.IsNullOrWhiteSpace( scriptfile ) )
  87. 					{
  88. 						return ShowHelp( "Duplicate command line argument for VBScript file" );
  89. 					}
  90. 					if ( !File.Exists( arg ) )
  91. 					{
  92. 						return ShowHelp( "Invalid file name or file not found: \"{0}\"", arg );
  93. 					}
  94. 					if ( Path.GetExtension( arg ).ToLower( ) != ".hta" && Path.GetExtension( arg ).ToLower( ) != ".vbs" )
  95. 					{
  96. 						return ShowHelp( "Invalid file type \"{0}\"", arg );
  97. 					}
  98. 					scriptfile = Path.GetFullPath( arg );
  99. 				}
  100.  
  101. 			}
  102.  
  103. 			if ( String.IsNullOrWhiteSpace( scriptfile ) )
  104. 			{
  105. 				return ShowHelp( "Please specify a source file" );
  106. 			}
  107.  
  108. 			#endregion Command Line Parsing
  109.  
  110.  
  111. 			#region Read File
  112.  
  113. 			// Read the code from the file
  114. 			scriptcode = File.ReadAllText( scriptfile, Encoding.UTF8 );
  115. 			// Remove comment lines from the code (does NOT strip comments starting halfway on a line)
  116. 			string pattern = @"(^|\n|\r)[ \t]*'[^\n\r]+";
  117. 			Regex regex = new Regex( pattern );
  118. 			scriptcode = regex.Replace( scriptcode, String.Empty );
  119.  
  120.  
  121. 			#endregion Read File
  122.  
  123.  
  124. 			#region List Subroutines
  125.  
  126. 			// Create a list of subroutines found in the code
  127. 			if ( showsubs )
  128. 			{
  129. 				pattern = @"(?:^|\n|\r)[ \t]*(?:Sub|Function)[ \t]+([A-Z][^\s\(]+)";
  130. 				regex = new Regex( pattern, RegexOptions.IgnoreCase );
  131. 				if ( regex.IsMatch( scriptcode ) )
  132. 				{
  133. 					MatchCollection matches = regex.Matches( scriptcode );
  134. 					if ( matches.Count > 0 )
  135. 					{
  136. 						foreach ( Match match in matches )
  137. 						{
  138. 							bool listed = false;
  139. 							string sub = match.Groups[1].ToString( );
  140. 							foreach ( string key in subroutines.Keys )
  141. 							{
  142. 								if ( sub.ToLower( ) == key.ToLower( ) )
  143. 								{
  144. 									listed = true;
  145. 								}
  146. 							}
  147. 							if ( !listed )
  148. 							{
  149. 								subroutines[sub] = 0;
  150. 								if ( sub.Length > columnwidth )
  151. 								{
  152. 									columnwidth = sub.Length;
  153. 								}
  154. 							}
  155. 						}
  156. 					}
  157. 				}
  158. 			}
  159.  
  160. 			#endregion List Subroutines
  161.  
  162.  
  163. 			#region List Variables
  164.  
  165. 			// Create a list of variables found in the code
  166. 			if ( showvars )
  167. 			{
  168. 				pattern = @"(?:^|\n|\r)[ \t]*Dim[ \t]+([A-Z][^\n\r:]+)";
  169. 				regex = new Regex( pattern, RegexOptions.IgnoreCase );
  170. 				if ( regex.IsMatch( scriptcode ) )
  171. 				{
  172. 					MatchCollection matches = regex.Matches( scriptcode );
  173. 					if ( matches.Count > 0 )
  174. 					{
  175. 						foreach ( Match match in matches )
  176. 						{
  177. 							string[] vars = match.Groups[1].ToString( ).Split( ", ()".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries );
  178. 							foreach ( string var in vars )
  179. 							{
  180. 								bool listed = false;
  181. 								foreach ( string key in subroutines.Keys )
  182. 								{
  183. 									if ( var.ToLower( ) == key.ToLower( ) )
  184. 									{
  185. 										listed = true;
  186. 									}
  187. 								}
  188. 								if ( !listed )
  189. 								{
  190. 									variables[var] = 0;
  191. 									if ( var.Length > columnwidth )
  192. 									{
  193. 										columnwidth = var.Length;
  194. 									}
  195. 								}
  196. 							}
  197. 						}
  198. 					}
  199. 				}
  200. 			}
  201.  
  202. 			#endregion List Variables
  203.  
  204.  
  205. 			#region Count and Display Subroutines Usage
  206.  
  207. 			// Iterate through the list of subroutines and count the occurences of its name
  208. 			if ( showsubs )
  209. 			{
  210. 				List<string> keys = new List<string>( subroutines.Keys );
  211. 				foreach ( string sub in keys )
  212. 				{
  213. 					pattern = String.Format( @"\b{0}\b", sub );
  214. 					regex = new Regex( pattern, RegexOptions.IgnoreCase );
  215. 					if ( regex.IsMatch( scriptcode ) )
  216. 					{
  217. 						subroutines[sub] = regex.Matches( scriptcode ).Count - 1;
  218. 					}
  219. 				}
  220. 				// Show the results
  221. 				if ( unusedonly )
  222. 				{
  223. 					Console.WriteLine( "Unused Subroutines:" );
  224. 					Console.WriteLine( "===================" );
  225. 				}
  226. 				else
  227. 				{
  228. 					Console.WriteLine( "{0,-" + columnwidth + "}    Occurences:", "Subroutine:" );
  229. 					Console.WriteLine( "{0,-" + columnwidth + "}    ===========", "===========" );
  230. 				}
  231. 				foreach ( string key in subroutines.Keys )
  232. 				{
  233. 					if ( subroutines[key] == 0 )
  234. 					{
  235. 						if ( unusedonly )
  236. 						{
  237. 							Console.WriteLine( key );
  238. 						}
  239. 						else
  240. 						{
  241. 							RedLine( String.Format( "{0,-" + columnwidth + "}    {1}", key, subroutines[key] ) );
  242. 						}
  243. 						rc += 1;
  244. 					}
  245. 					else if ( !unusedonly )
  246. 					{
  247. 						Console.WriteLine( "{0,-" + columnwidth + "}    {1}", key, subroutines[key] );
  248. 					}
  249. 				}
  250. 				Console.WriteLine( );
  251. 			}
  252.  
  253. 			#endregion Count and Display Subroutines Usage
  254.  
  255.  
  256. 			#region Count and Display Variables Usage
  257.  
  258. 			// Iterate through the list of variables and count the occurences of its name
  259. 			if ( showvars )
  260. 			{
  261. 				List<string> keys = new List<string>( variables.Keys );
  262. 				foreach ( string variable in keys )
  263. 				{
  264. 					pattern = String.Format( @"\b{0}\b", variable );
  265. 					regex = new Regex( pattern, RegexOptions.IgnoreCase );
  266. 					if ( regex.IsMatch( scriptcode ) )
  267. 					{
  268. 						variables[variable] = regex.Matches( scriptcode ).Count - 1;
  269. 					}
  270. 				}
  271. 				// Show the results
  272. 				if ( unusedonly )
  273. 				{
  274. 					Console.WriteLine( "Unused Variables:" );
  275. 					Console.WriteLine( "=================" );
  276. 				}
  277. 				else
  278. 				{
  279. 					Console.WriteLine( "{0,-" + columnwidth + "}    Occurences:", "Variable:" );
  280. 					Console.WriteLine( "{0,-" + columnwidth + "}    ===========", "=========" );
  281. 				}
  282. 				foreach ( string key in variables.Keys )
  283. 				{
  284. 					if ( variables[key] == 0 )
  285. 					{
  286. 						if ( unusedonly )
  287. 						{
  288. 							Console.WriteLine( key );
  289. 						}
  290. 						else
  291. 						{
  292. 							RedLine( String.Format( "{0,-" + columnwidth + "}    {1}", key, variables[key] ) );
  293. 						}
  294. 						rc += 1;
  295. 					}
  296. 					else if ( !unusedonly )
  297. 					{
  298. 						Console.WriteLine( "{0,-" + columnwidth + "}    {1}", key, variables[key] );
  299. 					}
  300. 				}
  301. 				Console.WriteLine( );
  302. 			}
  303.  
  304. 			#endregion Count and Display Variables Usage
  305.  
  306.  
  307. 			return rc;
  308. 		}
  309.  
  310.  
  311. 		static void RedLine( string line )
  312. 		{
  313. 			Console.ForegroundColor = ConsoleColor.Red;
  314. 			Console.WriteLine( line );
  315. 			Console.ResetColor( );
  316. 		}
  317.  
  318.  
  319. 		static int ShowHelp( params string[] errmsg )
  320. 		{
  321. 			#region Error Message
  322.  
  323. 			if ( errmsg.Length > 0 )
  324. 			{
  325. 				List<string> errargs = new List<string>( errmsg );
  326. 				errargs.RemoveAt( 0 );
  327. 				Console.Error.WriteLine( );
  328. 				Console.ForegroundColor = ConsoleColor.Red;
  329. 				Console.Error.Write( "ERROR:\t" );
  330. 				Console.ForegroundColor = ConsoleColor.White;
  331. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  332. 				Console.ResetColor( );
  333. 			}
  334.  
  335. 			#endregion Error Message
  336.  
  337.  
  338. 			#region Help Text
  339.  
  340. 			/*
  341. 			CheckVarsVBS.exe,  Version 1.00
  342. 			Check VBScript code for unused variables and subroutines
  343.  
  344. 			Usage:    CheckVarsVBS.exe  "vbsfile"  [ /U ]  [ /S | /V ]
  345.  
  346. 			Where:    "vbsfile"         is the VBScript or HTA file to be examined
  347. 			          /S                tests Subroutines only
  348. 			                            (default: subroutines as well as variables)
  349. 			          /U                list Unused subroutines and variables only
  350. 			                            (default: list all subroutines and variables)
  351. 			          /V                tests Variables only
  352. 			                            (default: subroutines as well as variables)
  353.  
  354. 			Note:     The program's return code equals the number of unused subroutines
  355. 			          and/or variables, or -1 in case of (command line) errors.
  356.  
  357. 			Written by Rob van der Woude
  358. 			http://www.robvanderwoude.com
  359. 			*/
  360.  
  361. 			Console.Error.WriteLine( );
  362.  
  363. 			Console.Error.WriteLine( "CheckVarsVBS.exe,  Version {0}", progver );
  364.  
  365. 			Console.Error.WriteLine( "Check VBScript code for unused variables and subroutines" );
  366.  
  367. 			Console.Error.WriteLine( );
  368.  
  369. 			Console.Error.Write( "Usage:    " );
  370. 			Console.ForegroundColor = ConsoleColor.White;
  371. 			Console.Error.WriteLine( "CheckVarsVBS.exe  \"vbsfile\"  [ /U ]  [ /S | /V ]" );
  372. 			Console.ResetColor( );
  373.  
  374. 			Console.Error.WriteLine( );
  375.  
  376. 			Console.Error.Write( "Where:    " );
  377. 			Console.ForegroundColor = ConsoleColor.White;
  378. 			Console.Error.Write( "\"vbsfile\"" );
  379. 			Console.ResetColor( );
  380. 			Console.Error.WriteLine( "         is the VBScript or HTA file to be examined" );
  381.  
  382. 			Console.ForegroundColor = ConsoleColor.White;
  383. 			Console.Error.Write( "          /S" );
  384. 			Console.ResetColor( );
  385. 			Console.Error.Write( "                tests " );
  386. 			Console.ForegroundColor = ConsoleColor.White;
  387. 			Console.Error.Write( "S" );
  388. 			Console.ResetColor( );
  389. 			Console.Error.WriteLine( "ubroutines only" );
  390.  
  391. 			Console.Error.WriteLine( "                            (default: subroutines as well as variables)" );
  392.  
  393. 			Console.ForegroundColor = ConsoleColor.White;
  394. 			Console.Error.Write( "          /U" );
  395. 			Console.ResetColor( );
  396. 			Console.Error.Write( "                list " );
  397. 			Console.ForegroundColor = ConsoleColor.White;
  398. 			Console.Error.Write( "U" );
  399. 			Console.ResetColor( );
  400. 			Console.Error.WriteLine( "nused subroutines and variables only" );
  401.  
  402. 			Console.Error.WriteLine( "                            (default: list all subroutines and variables)" );
  403.  
  404. 			Console.ForegroundColor = ConsoleColor.White;
  405. 			Console.Error.Write( "          /V" );
  406. 			Console.ResetColor( );
  407. 			Console.Error.Write( "                tests " );
  408. 			Console.ForegroundColor = ConsoleColor.White;
  409. 			Console.Error.Write( "V" );
  410. 			Console.ResetColor( );
  411. 			Console.Error.WriteLine( "ariables only" );
  412.  
  413. 			Console.Error.WriteLine( "                            (default: subroutines as well as variables)" );
  414.  
  415. 			Console.Error.WriteLine( );
  416.  
  417. 			Console.Error.WriteLine( "Note:     The program's return code equals the number of unused subroutines" );
  418.  
  419. 			Console.Error.WriteLine( "          and/or variables, or -1 in case of (command line) errors." );
  420.  
  421. 			Console.Error.WriteLine( );
  422.  
  423. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  424.  
  425. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  426.  
  427. 			#endregion Help Text
  428.  
  429.  
  430. 			return -1;
  431. 		}
  432. 	}
  433. }
  434.  

page last uploaded: 2017-04-06, 13:33