Powered by GeSHi

Source code for pingsite.cs

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

  1. using System;
  2. using System.Media;
  3. using System.Net;
  4. using System.Threading;
  5.  
  6. namespace RobvanderWoude
  7. {
  8. 	class PingSite
  9. 	{
  10. 		static bool beep = false;
  11.  
  12. 		static int Main( string[] args )
  13. 		{
  14. 			try
  15. 			{
  16.  
  17. 				// Default values
  18. 				bool varSpeed = false;
  19. 				bool verbose = true;
  20. 				bool changes = false;
  21. 				int interval = 0;
  22. 				int fastInt = 0;
  23. 				int slowInt = 0;
  24. 				int previous = 0;
  25. 				string expected = string.Empty;
  26. 				string url = string.Empty;
  27.  
  28. 				#region Command Line Parsing
  29.  
  30. 				// Custom error message
  31. 				string msgInvalid = "Invalid command line argument" + ( ( args.Length == 1 ) ? string.Empty : "(s)" );
  32.  
  33. 				// No command line arguments? Display help
  34. 				if ( args.Length == 0 )
  35. 				{
  36. 					return WriteError( string.Empty );
  37. 				}
  38.  
  39. 				foreach ( string arg in args )
  40. 				{
  41. 					// Check switches first
  42. 					switch ( arg.ToLower( ).Substring( 0, 2 ) )
  43. 					{
  44. 						case "/?":
  45. 						case "-?":
  46. 						case "/h":
  47. 						case "-h":
  48. 							// Display help
  49. 							return WriteError( string.Empty );
  50. 						case "--":
  51. 							if ( arg.ToLower( ) == "--help" )
  52. 							{
  53. 								// Display help
  54. 								return WriteError( string.Empty );
  55. 							}
  56. 							else
  57. 							{
  58. 								// Display error message
  59. 								return WriteError( msgInvalid );
  60. 							}
  61. 						case "/b":
  62. 							beep = true;
  63. 							break;
  64. 						case "/c":
  65. 							verbose = false;
  66. 							changes = true;
  67. 							break;
  68. 						case "/i":
  69. 							if ( arg.ToLower( ).StartsWith( "/i:" ) || arg.ToLower( ).StartsWith( "/interval:" ) )
  70. 							{
  71. 								slowInt = System.Convert.ToInt32( arg.Substring( arg.IndexOf( ":" ) + 1 ) );
  72. 								if ( slowInt < 1 )
  73. 								{
  74. 									return WriteError( "Interval must be 1 or greater" );
  75. 								}
  76. 							}
  77. 							else
  78. 							{
  79. 								return WriteError( msgInvalid );
  80. 							}
  81. 							break;
  82. 						case "/q":
  83. 							verbose = false;
  84. 							changes = false;
  85. 							break;
  86. 						case "/s":
  87. 							{
  88. 								if ( arg.IndexOf( ":" ) > 0 )
  89. 								{
  90. 									expected = arg.Substring( arg.IndexOf( ":" ) + 1 ).ToUpper( );
  91. 								}
  92. 								else
  93. 								{
  94. 									expected = "OK";
  95. 								}
  96. 								if ( expected == "OK" )
  97. 								{
  98. 									expected = "200,301,302,303,304,305,306,307";
  99. 								}
  100. 							}
  101. 							break;
  102. 						case "/v":
  103. 							varSpeed = true;
  104. 							break;
  105. 						default:
  106. 							url = arg;
  107. 							break;
  108. 					}
  109. 				}
  110.  
  111. 				if ( string.IsNullOrEmpty( url ) )
  112. 				{
  113. 					return WriteError( "An URL must be specified" );
  114. 				}
  115.  
  116. 				if ( slowInt < 1 && changes )
  117. 				{
  118. 					return WriteError( "To display status changes only, an interval must be specified" );
  119. 				}
  120.  
  121. 				if ( slowInt > 0 && !( verbose || changes ) )
  122. 				{
  123. 					return WriteError( "/Quiet switch not allowed if an interval is specified" );
  124. 				}
  125.  
  126. 				if ( varSpeed && ( string.IsNullOrEmpty( expected ) || slowInt < 1 ) )
  127. 				{
  128. 					return WriteError( "/Variable requires both /Status and /Interval" );
  129. 				}
  130.  
  131. 				interval = slowInt;
  132. 				if ( slowInt >= 25 )
  133. 				{
  134. 					fastInt = slowInt / 5;
  135. 				}
  136. 				else if ( slowInt < 5 )
  137. 				{
  138. 					fastInt = slowInt;
  139. 				}
  140. 				else
  141. 				{
  142. 					fastInt = 5;
  143. 				}
  144.  
  145. 				#endregion Command Line Parsing
  146.  
  147. 				// Loop will be aborted if interval is less than 1
  148. 				while ( true )
  149. 				{
  150. 					HttpStatusCode status = GetResponse( url );
  151. 					string statusText = status.ToString( );
  152. 					int statusCode = (int) status;
  153.  
  154. 					// Display result
  155. 					if ( ( ( previous != statusCode ) && changes ) || verbose )
  156. 					{
  157. 						ConsoleColor statusColor;
  158. 						if ( string.IsNullOrEmpty( expected ) || expected.Contains( statusCode.ToString( ) ) )
  159. 						{
  160. 							statusColor = ConsoleColor.White;
  161. 							interval = slowInt;
  162. 						}
  163. 						else
  164. 						{
  165. 							statusColor = ConsoleColor.Red;
  166. 							if ( varSpeed )
  167. 							{
  168. 								interval = fastInt;
  169. 							}
  170. 						}
  171. 						Console.Write( "[{0}]\t", DateTime.Now );
  172. 						Console.ForegroundColor = statusColor;
  173. 						Console.Write( "{0}\t{1}", statusCode, statusText );
  174. 						Console.ResetColor( );
  175. 						Console.WriteLine( "\t{0}", url );
  176. 						Console.Title = "PingSite: " + statusCode.ToString( );
  177. 						// Beep on changes, if requested
  178. 						if ( beep )
  179. 						{
  180. 							bool beepNow = false;
  181. 							if ( changes )
  182. 							{
  183. 								beepNow = true;
  184. 							}
  185. 							if ( string.IsNullOrEmpty( expected ) == false )
  186. 							{
  187. 								if ( expected.Contains( statusCode.ToString( ) ) == false )
  188. 								{
  189. 									beepNow = true;
  190. 								}
  191. 							}
  192. 							if ( beepNow )
  193. 							{
  194. 								Console.Beep( );
  195. 							}
  196. 						}
  197. 					}
  198.  
  199. 					// Save the last status code to compare it in the next iteration of the loop
  200. 					previous = statusCode;
  201.  
  202. 					// Break the loop if interval is less than 1
  203. 					if ( interval < 1 )
  204. 					{
  205. 						if ( string.IsNullOrEmpty( expected ) )
  206. 						{
  207. 							// Return the actual status code
  208. 							return statusCode;
  209. 						}
  210. 						else
  211. 						{
  212. 							// If we were monitoring for an expected code, return either 0 (match) or 2 (no match)
  213. 							return ( ( expected.Contains( statusCode.ToString( ) ) ) ? 0 : 2 );
  214. 						}
  215. 					}
  216.  
  217. 					// Wait for the specified number of seconds
  218. 					Thread.Sleep( interval * 1000 );
  219. 				}
  220. 			}
  221. 			catch ( Exception e )
  222. 			{
  223. 				return WriteError( e.Message );
  224. 			}
  225. 		}
  226.  
  227. 		public static HttpStatusCode GetResponse( string url )
  228. 		{
  229. 			// Returns the HTTP Status Code for the specified URL, or 0 on errors
  230. 			try
  231. 			{
  232. 				HttpWebRequest req = (HttpWebRequest) WebRequest.Create( url );
  233. 				req.AllowAutoRedirect = false;
  234. 				HttpWebResponse resp = (HttpWebResponse) req.GetResponse( );
  235. 				HttpStatusCode stat = resp.StatusCode;
  236. 				req.Abort( );
  237. 				return stat;
  238. 			}
  239. 			catch ( WebException e )
  240. 			{
  241. 				// Handle exceptions caused by the server response, e.g. 404
  242. 				try
  243. 				{
  244. 					HttpWebResponse httpResponse = (HttpWebResponse) e.Response;
  245. 					return httpResponse.StatusCode;
  246. 				}
  247. 				// Handle the "real" exceptions
  248. 				catch
  249. 				{
  250. 					WriteError( e.Message, false );
  251. 					return 0;
  252. 				}
  253. 			}
  254. 			catch ( Exception e )
  255. 			{
  256. 				WriteError( e.Message );
  257. 				return 0;
  258. 			}
  259. 		}
  260.  
  261. 		#region Error Handling
  262.  
  263. 		public static int WriteError( Exception e )
  264. 		{
  265. 			return WriteError( e == null ? null : e.Message );
  266. 		}
  267.  
  268. 		public static int WriteError( string errorMessage, bool showHelp = true )
  269. 		{
  270. 			/*
  271. 			PingSite,  Version 1.21
  272. 			Check if a website is up and running
  273.  
  274. 			Usage:  PINGSITE  url  [ /Status[:expected] ]  [ /Interval:seconds ]
  275. 			                       [ /Variable ]  [ /Beep ]  [ /Changes | /Quiet ]
  276.  
  277. 			Where:  url        is the URL of the site or page to check (including http://)
  278. 			        /Beep      beep on changes or if response does not match expected
  279. 			        /Changes   display status changes only (requires /Interval)
  280. 			        /Interval  defines the optional interval in seconds between checks
  281. 			                   (default if not specified: terminate after 1 check)
  282. 			        /Quiet     no screen output, 'errorlevel' only
  283. 			        /Status    is either the expected numeric HTTP response code, or
  284. 			                   'OK' for 200, 301..307 (default)
  285. 			        /Variable  shorter interval on mismatch (requires /Interval & /Status)
  286.  
  287. 			Notes:  If /Status was used, 'errorlevel' 0 is returned if status matches
  288. 			        expected, 2 if not; otherwise the actual status code is returned as
  289. 			        'errorlevel'; in case of (command line) errors 1 is returned.
  290. 			        Switches /Interval and /Quiet are mutually exclusive.
  291. 			        Switches may be abbreviated, e.g. /I instead of /Interval.
  292.  
  293. 			Written by Rob van der Woude
  294. 			http://www.robvanderwoude.com
  295. 			*/
  296.  
  297. 			if ( string.IsNullOrEmpty( errorMessage ) == false )
  298. 			{
  299. 				Console.Error.WriteLine( );
  300. 				Console.ForegroundColor = ConsoleColor.Red;
  301. 				Console.Error.Write( "ERROR:  " );
  302. 				Console.ForegroundColor = ConsoleColor.White;
  303. 				Console.Error.WriteLine( errorMessage );
  304. 				Console.ResetColor( );
  305. 				if ( beep )
  306. 				{
  307. 					Console.Beep( );
  308. 				}
  309. 			}
  310. 			if ( showHelp )
  311. 			{
  312. 				Console.Error.WriteLine( );
  313. 				Console.Error.WriteLine( "PingSite,  Version 1.21" );
  314. 				Console.Error.WriteLine( "Check if a website is up and running" );
  315. 				Console.Error.WriteLine( );
  316. 				Console.Error.Write( "Usage: " );
  317. 				Console.ForegroundColor = ConsoleColor.White;
  318. 				Console.Error.WriteLine( "PINGSITE  url  [ /Status[:expected] ]  [ /Interval:seconds ]" );
  319. 				Console.Error.WriteLine( "                      [ /Variable ]  [ /Beep ]  [ /Changes | /Quiet ]" );
  320. 				Console.ResetColor( );
  321. 				Console.Error.WriteLine( );
  322. 				Console.Error.WriteLine( "Where:  url        is the URL of the site or page to check (including http://)" );
  323. 				Console.ForegroundColor = ConsoleColor.White;
  324. 				Console.Error.Write( "        /B" );
  325. 				Console.ResetColor( );
  326. 				Console.Error.WriteLine( "eep      beep on changes or if response does not match expected" );
  327. 				Console.ForegroundColor = ConsoleColor.White;
  328. 				Console.Error.Write( "        /C" );
  329. 				Console.ResetColor( );
  330. 				Console.Error.Write( "hanges   display status changes only (requires " );
  331. 				Console.ForegroundColor = ConsoleColor.White;
  332. 				Console.Error.Write( "/I" );
  333. 				Console.ResetColor( );
  334. 				Console.Error.WriteLine( "nterval)" );
  335. 				Console.ForegroundColor = ConsoleColor.White;
  336. 				Console.Error.Write( "        /I" );
  337. 				Console.ResetColor( );
  338. 				Console.Error.WriteLine( "nterval  defines the optional interval in seconds between checks" );
  339. 				Console.Error.WriteLine( "                   (default if not specified: terminate after 1 check)" );
  340. 				Console.ForegroundColor = ConsoleColor.White;
  341. 				Console.ForegroundColor = ConsoleColor.White;
  342. 				Console.Error.Write( "        /Q" );
  343. 				Console.ResetColor( );
  344. 				Console.Error.WriteLine( "uiet     no screen output, 'errorlevel' only" );
  345. 				Console.ForegroundColor = ConsoleColor.White;
  346. 				Console.Error.Write( "        /S" );
  347. 				Console.ResetColor( );
  348. 				Console.Error.WriteLine( "tatus    is either the expected numeric HTTP response code, or" );
  349. 				Console.Error.WriteLine( "                   'OK' for 200, 301..307 (default)" );
  350. 				Console.ForegroundColor = ConsoleColor.White;
  351. 				Console.Error.Write( "        /V" );
  352. 				Console.ResetColor( );
  353. 				Console.Error.Write( "ariable  shorter interval on mismatch (requires " );
  354. 				Console.ForegroundColor = ConsoleColor.White;
  355. 				Console.Error.Write( "/I" );
  356. 				Console.ResetColor( );
  357. 				Console.Error.Write( "nterval & " );
  358. 				Console.ForegroundColor = ConsoleColor.White;
  359. 				Console.Error.Write( "/S" );
  360. 				Console.ResetColor( );
  361. 				Console.Error.WriteLine( "tatus)" );
  362. 				Console.Error.WriteLine( );
  363. 				Console.Error.Write( "Notes: If " );
  364. 				Console.ForegroundColor = ConsoleColor.White;
  365. 				Console.Error.Write( "/S" );
  366. 				Console.ResetColor( );
  367. 				Console.Error.WriteLine( "tatus was used, 'errorlevel' 0 is returned if status matches" );
  368. 				Console.Error.WriteLine( "       expected, 2 if not; otherwise the actual status code is returned as" );
  369. 				Console.Error.WriteLine( "       'errorlevel'; in case of (command line) errors 1 is returned." );
  370. 				Console.Error.Write( "       Switches " );
  371. 				Console.ForegroundColor = ConsoleColor.White;
  372. 				Console.Error.Write( "/I" );
  373. 				Console.ResetColor( );
  374. 				Console.Error.Write( "nterval and " );
  375. 				Console.ForegroundColor = ConsoleColor.White;
  376. 				Console.Error.Write( "/Q" );
  377. 				Console.ResetColor( );
  378. 				Console.Error.WriteLine( "uiet are mutually exclusive." );
  379. 				Console.Error.Write( "       Switches may be abbreviated, e.g. " );
  380. 				Console.ForegroundColor = ConsoleColor.White;
  381. 				Console.Error.Write( "/I" );
  382. 				Console.ResetColor( );
  383. 				Console.Error.Write( " instead of " );
  384. 				Console.ForegroundColor = ConsoleColor.White;
  385. 				Console.Error.Write( "/I" );
  386. 				Console.ResetColor( );
  387. 				Console.Error.WriteLine( "nterval." );
  388. 				Console.Error.WriteLine( );
  389. 				Console.Error.WriteLine( "Written by Rob van der Woude" );
  390. 				Console.Error.Write( "http://www.robvanderwoude.com" );
  391. 			}
  392. 			return 1;
  393. 		}
  394.  
  395. 		#endregion Error Handling
  396. 	}
  397. }
  398.