(view source code of pingsite.cs as plain text)
using System;
using System.Media;
using System.Net;
using System.Threading;
namespace RobvanderWoude
{
class PingSite
{
static bool beep = false;
static int Main( string[] args )
{
try
{
// Default values
bool varSpeed = false;
bool verbose = true;
bool changes = false;
int interval = 0;
int fastInt = 0;
int slowInt = 0;
int previous = 0;
string expected = string.Empty;
string url = string.Empty;
#region Command Line Parsing
// Custom error message
string msgInvalid = "Invalid command line argument" + ( ( args.Length == 1 ) ? string.Empty : "(s)" );
// No command line arguments? Display help
if ( args.Length == 0 )
{
return WriteError( string.Empty );
}
foreach ( string arg in args )
{
// Check switches first
switch ( arg.ToLower( ).Substring( 0, 2 ) )
{
case "/?":
case "-?":
case "/h":
case "-h":
// Display help
return WriteError( string.Empty );
case "--":
if ( arg.ToLower( ) == "--help" )
{
// Display help
return WriteError( string.Empty );
}
else
{
// Display error message
return WriteError( msgInvalid );
}
case "/b":
beep = true;
break;
case "/c":
verbose = false;
changes = true;
break;
case "/i":
if ( arg.ToLower( ).StartsWith( "/i:" ) || arg.ToLower( ).StartsWith( "/interval:" ) )
{
slowInt = System.Convert.ToInt32( arg.Substring( arg.IndexOf( ":" ) + 1 ) );
if ( slowInt < 1 )
{
return WriteError( "Interval must be 1 or greater" );
}
}
else
{
return WriteError( msgInvalid );
}
break;
case "/q":
verbose = false;
changes = false;
break;
case "/s":
{
if ( arg.IndexOf( ":" ) > 0 )
{
expected = arg.Substring( arg.IndexOf( ":" ) + 1 ).ToUpper( );
}
else
{
expected = "OK";
}
if ( expected == "OK" )
{
expected = "200,301,302,303,304,305,306,307";
}
}
break;
case "/v":
varSpeed = true;
break;
default:
url = arg;
break;
}
}
if ( string.IsNullOrEmpty( url ) )
{
return WriteError( "An URL must be specified" );
}
if ( slowInt < 1 && changes )
{
return WriteError( "To display status changes only, an interval must be specified" );
}
if ( slowInt > 0 && !( verbose || changes ) )
{
return WriteError( "/Quiet switch not allowed if an interval is specified" );
}
if ( varSpeed && ( string.IsNullOrEmpty( expected ) || slowInt < 1 ) )
{
return WriteError( "/Variable requires both /Status and /Interval" );
}
interval = slowInt;
if ( slowInt >= 25 )
{
fastInt = slowInt / 5;
}
else if ( slowInt < 5 )
{
fastInt = slowInt;
}
else
{
fastInt = 5;
}
#endregion Command Line Parsing
// Loop will be aborted if interval is less than 1
while ( true )
{
HttpStatusCode status = GetResponse( url );
string statusText = status.ToString( );
int statusCode = (int) status;
// Display result
if ( ( ( previous != statusCode ) && changes ) || verbose )
{
ConsoleColor statusColor;
if ( string.IsNullOrEmpty( expected ) || expected.Contains( statusCode.ToString( ) ) )
{
statusColor = ConsoleColor.White;
interval = slowInt;
}
else
{
statusColor = ConsoleColor.Red;
if ( varSpeed )
{
interval = fastInt;
}
}
Console.Write( "[{0}]\t", DateTime.Now );
Console.ForegroundColor = statusColor;
Console.Write( "{0}\t{1}", statusCode, statusText );
Console.ResetColor( );
Console.WriteLine( "\t{0}", url );
Console.Title = "PingSite: " + statusCode.ToString( );
// Beep on changes, if requested
if ( beep )
{
bool beepNow = false;
if ( changes )
{
beepNow = true;
}
if ( string.IsNullOrEmpty( expected ) == false )
{
if ( expected.Contains( statusCode.ToString( ) ) == false )
{
beepNow = true;
}
}
if ( beepNow )
{
Console.Beep( );
}
}
}
// Save the last status code to compare it in the next iteration of the loop
previous = statusCode;
// Break the loop if interval is less than 1
if ( interval < 1 )
{
if ( string.IsNullOrEmpty( expected ) )
{
// Return the actual status code
return statusCode;
}
else
{
// If we were monitoring for an expected code, return either 0 (match) or 2 (no match)
return ( ( expected.Contains( statusCode.ToString( ) ) ) ? 0 : 2 );
}
}
// Wait for the specified number of seconds
Thread.Sleep( interval * 1000 );
}
}
catch ( Exception e )
{
return WriteError( e.Message );
}
}
public static HttpStatusCode GetResponse( string url )
{
// Returns the HTTP Status Code for the specified URL, or 0 on errors
try
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create( url );
req.AllowAutoRedirect = false;
HttpWebResponse resp = (HttpWebResponse) req.GetResponse( );
HttpStatusCode stat = resp.StatusCode;
req.Abort( );
return stat;
}
catch ( WebException e )
{
// Handle exceptions caused by the server response, e.g. 404
try
{
HttpWebResponse httpResponse = (HttpWebResponse) e.Response;
return httpResponse.StatusCode;
}
// Handle the "real" exceptions
catch
{
WriteError( e.Message, false );
return 0;
}
}
catch ( Exception e )
{
WriteError( e.Message );
return 0;
}
}
#region Error Handling
public static int WriteError( Exception e )
{
return WriteError( e == null ? null : e.Message );
}
public static int WriteError( string errorMessage, bool showHelp = true )
{
/*
PingSite, Version 1.21
Check if a website is up and running
Usage: PINGSITE url [ /Status[:expected] ] [ /Interval:seconds ]
[ /Variable ] [ /Beep ] [ /Changes | /Quiet ]
Where: url is the URL of the site or page to check (including http://)
/Beep beep on changes or if response does not match expected
/Changes display status changes only (requires /Interval)
/Interval defines the optional interval in seconds between checks
(default if not specified: terminate after 1 check)
/Quiet no screen output, 'errorlevel' only
/Status is either the expected numeric HTTP response code, or
'OK' for 200, 301..307 (default)
/Variable shorter interval on mismatch (requires /Interval & /Status)
Notes: If /Status was used, 'errorlevel' 0 is returned if status matches
expected, 2 if not; otherwise the actual status code is returned as
'errorlevel'; in case of (command line) errors 1 is returned.
Switches /Interval and /Quiet are mutually exclusive.
Switches may be abbreviated, e.g. /I instead of /Interval.
Written by Rob van der Woude
http://www.robvanderwoude.com
*/
if ( string.IsNullOrEmpty( errorMessage ) == false )
{
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errorMessage );
Console.ResetColor( );
if ( beep )
{
Console.Beep( );
}
}
if ( showHelp )
{
Console.Error.WriteLine( );
Console.Error.WriteLine( "PingSite, Version 1.21" );
Console.Error.WriteLine( "Check if a website is up and running" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "PINGSITE url [ /Status[:expected] ] [ /Interval:seconds ]" );
Console.Error.WriteLine( " [ /Variable ] [ /Beep ] [ /Changes | /Quiet ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Where: url is the URL of the site or page to check (including http://)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /B" );
Console.ResetColor( );
Console.Error.WriteLine( "eep beep on changes or if response does not match expected" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /C" );
Console.ResetColor( );
Console.Error.Write( "hanges display status changes only (requires " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I" );
Console.ResetColor( );
Console.Error.WriteLine( "nterval)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /I" );
Console.ResetColor( );
Console.Error.WriteLine( "nterval defines the optional interval in seconds between checks" );
Console.Error.WriteLine( " (default if not specified: terminate after 1 check)" );
Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /Q" );
Console.ResetColor( );
Console.Error.WriteLine( "uiet no screen output, 'errorlevel' only" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /S" );
Console.ResetColor( );
Console.Error.WriteLine( "tatus is either the expected numeric HTTP response code, or" );
Console.Error.WriteLine( " 'OK' for 200, 301..307 (default)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /V" );
Console.ResetColor( );
Console.Error.Write( "ariable shorter interval on mismatch (requires " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I" );
Console.ResetColor( );
Console.Error.Write( "nterval & " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/S" );
Console.ResetColor( );
Console.Error.WriteLine( "tatus)" );
Console.Error.WriteLine( );
Console.Error.Write( "Notes: If " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/S" );
Console.ResetColor( );
Console.Error.WriteLine( "tatus was used, 'errorlevel' 0 is returned if status matches" );
Console.Error.WriteLine( " expected, 2 if not; otherwise the actual status code is returned as" );
Console.Error.WriteLine( " 'errorlevel'; in case of (command line) errors 1 is returned." );
Console.Error.Write( " Switches " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I" );
Console.ResetColor( );
Console.Error.Write( "nterval and " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/Q" );
Console.ResetColor( );
Console.Error.WriteLine( "uiet are mutually exclusive." );
Console.Error.Write( " Switches may be abbreviated, e.g. " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I" );
Console.ResetColor( );
Console.Error.Write( " instead of " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I" );
Console.ResetColor( );
Console.Error.WriteLine( "nterval." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.Write( "http://www.robvanderwoude.com" );
}
return 1;
}
#endregion Error Handling
}
}
page last modified: 2024-04-16; loaded in 0.0112 seconds