Any suggestions are welcome!
; AutoHotkey Script ; Script Name: Server Check ; Version: 2.3.2 ; Author: silveredge78 ; ; The purpose of this script is to periodcially check to see if specific ; servers are pingable (up and functioning properly) or unpingable (down and ; in need of attention). The reason this is necessary is to limit the amount ; of downtime should a server goes down. This program checks the status of ; the servers every X mins (where X = your preferred amount of time). If a ; server is found to be down for Y consecutive checks (where Y = your preferred ; number of failures), then it will send out notification(s) so that it can ; be addressed. ; ; This script uses Blat 2.62 (http://www.blat.net) for generating the email ; notifications. ; ; This script uses Alive 1.2 (http://members.aol.com/stevesfreeware/alive.zip or ; alternately found at https://ahknet.autohotkey.com/~silveredge78/Alive.zip) ; to do the ping check for ServerStatus. ; ; To implement: ; - Error checking if someone cancels out of Ini fields ; ; Changelog: ; Version 2.3.2, 12/20/07 ; - Tweaked MailAltFromString to be -from instead of -mailfrom. ; ; Version 2.3.1, 12/20/07 ; - Added in About/ TrayMenu option for easier future reference. ; - Moved MailAltFromString to the end of the blat command parameter string. ; ; Version 2.3.1, 12/10/07 ; - Added in MailAltFrom to allow Blat to send as if from a different address ; other than the one being used to authenticate. Allows for easier filtering ; in mail programs. ; - Adjusted Ini file generation, reading, etc as needed. ; - Adjusted some verbage in Ini creation dialog boxes for clarification. ; - Adjusted Notify() to allow for MailCCString and MailAltFromString for a ; cleaner call in the Run Blat command. ; - Adjusted Ini file to write all at once so that if there was an error creating ; it, it does not get written. ; ; Version 2.3.0, 12/06/07 ; - Changed recommended version of Blat from 2.50 to 2.62 to deal with ; some authentication issues @ GVM-C ; - Added %ScriptName% variable ; - Tweaked pop-up titles to use %ScriptName% ; - Adjusted frequency to be in seconds instead of minutes ; - Added in RC4 encryption (from NetworkAuthentication) ; - Made RC4Pass not username specific ; - Adjusted order of TrayMenu to put 'Show ini file' above 'Show log file' ; ; Version 2.2.3, 11/12/07 ; - Added Show Ini file option to tray menu. ; ; Version 2.2.2, 09/19/07 ; - Added Show Log option to tray menu, made it default ; ; Version 2.2.1, 08/29/07 ; - Modified the Notify() function to allow for an empty/missing MailCC variable ; ; Version 2.2.0, 02/23/07 ; - Revised logging logic to prevent multiple logging of same failure upon ; ServerDown = %Failures% and running of Notify() ; - Added %MailCC% variable to allow for a CC list, allowing for a single ; email to be generated rather than several. ; - Added to INI creation ; - This eliminates the %MailTo% parsing loop ; - Adjusted Notify() to reflect the change ; - Added mail server authorization for sending emails that would normally ; be considered 'relayed' ; - Added to INI creation, with prompt to add or not ; - Set MailPassword InputBox to HIDE ; - Added IniCheck() to make sure that all fields are read from the INI file. ; ; Version 2.1.2, 11/18/06 ; - Changed notification variable, function call to allow for multiple email ; addresses to notify ; - Changed name of TextMsg() to Notify() ; ; Version 2.1.1, 11/14/06 ; - Changed TextMsg() to call Log() to clean up the code. ; - Modified Message to log when a notification is sent for easier reading ; of the log file. ; - Added variable for ScriptLog ; ; Version 2.1.0, 11/12/06 ; - Revamped script to run from ini file for parameters ; - Server list ; - Frequency in minutes, Number of Failures ; - Mail server IP, to and from addresses ; - Set it to check for existing ini or to create one if missing ; - Added new global variable of 'Failures' for use in the ini ; - Changed how Server#, Server#Down and Server#State are generated to allow ; for dynamic creation at time of script run. ; - Added menu item for reloading/restarting the script ; ; Version 2.0.0, 8/29/06 ; - Replaced Ping function and String checking with Alive.exe ; - Allows for better error checking, and thus more accurate logging ; ; Version 1.1.0, 8/29/06 ; - Created ServerState variable to keep track of current state ; - Allows for multiple notifications based on a change of state ; ; Version 1.0.0, 8/29/06 ; - Initial version of script ; - Used ping function to check for server status (up/down) ; - Set checking to be adjustable based on Frequency ; - Enabled paging of administrator should a server fail 5 consecutive checks ; - Using Log() function from previous script ; - Using TextMsg() function from previous script ; - Modified to use global variables ; - Added custom tray menu and icon #Persistent #NoEnv #SingleInstance Force ;;;;;;;;;;;;;;;;;;;;;;;;;;Auto-Execute Section;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; set representative icon - DEBUG: optional Menu, Tray, Icon, Shell32.dll, 19, 1 ; construct tray menu - DEBUG: optional GoSub, TrayMenu ScriptName = Server Check ScriptVersion = v2.3.2 ScriptDate = 12/20/2007 SplitPath, A_ScriptName,,,, ScriptNoExt ScriptIni = %ScriptNoExt%.ini ScriptLog = %ScriptNoExt%.log RC4Pass = %WS_OS%`n%WS_Name%`n%WS_Processors%`nwww.autohotkey.com`n©2003-2005 Chris Mallett, portions ©AutoIt Team IfNotExist, %ScriptIni% { InputBox, MailServerIP, %ScriptName%, Please enter the email server's name/IP address to use: If ErrorLevel <> 0 GoSub, IniError InputBox, MailFrom, %ScriptName%, Please enter the email address to send failures *FROM*.`n`nPlease note that it needs to be an address that is authorized to send email on the email server previously chosen. If ErrorLevel <> 0 GoSub, IniError InputBox, MailAltFrom, %ScriptName%, Please enter an alternate email address to send failures *FROM*, if you would prefer to not use the authentication email address..`n`nPlease note that this does *not* need to be an address that is authorized to send email on the email server previously chosen. If ErrorLevel <> 0 GoSub, IniError InputBox, MailTo, %ScriptName%, Please enter the first email address to send failures *TO*. If ErrorLevel <> 0 GoSub, IniError InputBox, MailCC, %ScriptName%, Please enter any additional email addresses to send failures *TO*.`n`nPlease seperate multiple email addresses with a comma. If ErrorLevel <> 0 GoSub, IniError MsgBox, 36, %ScriptName%, Does your email server require authentication? IfMsgBox, No { MailUsername = MailPassword = } IfMsgBox, Yes { InputBox, MailUsername, %ScriptName%, Please enter your mail server *username*. If ErrorLevel <> 0 GoSub, IniError InputBox, MailPassword, %ScriptName%, Please enter your mail account password., HIDE If ErrorLevel <> 0 GoSub, IniError } ;MsgBox, MailUsername before RC4: %MailUsername%`nMailPassword before RC4: %MailPassword% ; For testing, enabled RC4MailUsername := RC4txt2hex(MailUserName,RC4Pass) RC4MailPassword := RC4txt2hex(MailPassword,RC4Pass) ;MsgBox, MailUsername after RC4: %RC4MailUsername%`nMailPassword after RC4: %RC4MailPassword% ; For testing, enabled InputBox, Frequency, %ScriptName%, Please enter how often you want to check your servers for connectivity in seconds. If ErrorLevel <> 0 GoSub, IniError InputBox, Failures, %ScriptName%, Please enter the number of consecutive failures to test for before notification occurs. If ErrorLevel <> 0 GoSub, IniError InputBox, NumberOfServers, %ScriptName%, Please enter the number of servers to check. If ErrorLevel <> 0 GoSub, IniError Loop, %NumberOfServers% { InputBox, Server, %ScriptName%, Please enter the network server name`, IP`, or domain of server number %A_Index%: If ErrorLevel <> 0 Break If ServerList = ServerList = %Server% Else ServerList = %ServerList%,%Server% } FileAppend, [Mail]`nMailServerIP=%MailServerIP%`nMailFrom=%MailFrom%`nMailAltFrom=%MailAltFrom%`nMailTo=%MailTo%`nMailCC=%MailCC%`nMailUsername=%RC4MailUsername%`nMailPassword=%RC4MailPassword%`n`n[Checking]`nFrequency=%Frequency%`nFailures=%Failures%`n`n[Servers]`nServerList=%ServerList%`n, %ScriptIni% } IniRead, MailServerIP, %ScriptIni%, Mail, MailServerIP IniCheck("MailServerIP") IniRead, MailFrom, %ScriptIni%, Mail, MailFrom IniCheck("MailFrom") IniRead, MailAltFrom, %ScriptIni%, Mail, MailAltFrom IniCheck("MailAltFrom") IniRead, MailTo, %ScriptIni%, Mail, MailTo IniCheck("MailTo") IniRead, MailCC, %ScriptIni%, Mail, MailCC IniCheck("MailCC") IniRead, RC4MailUsername, %ScriptIni%, Mail, MailUsername IniCheck("MailUsername") IniRead, RC4MailPassword, %ScriptIni%, Mail, MailPassword IniCheck("MailPassword") IniRead, Frequency, %ScriptIni%, Checking, Frequency IniCheck("Frequency") IniRead, Failures, %ScriptIni%, Checking, Failures IniCheck("Failures") IniRead, ServerList, %ScriptIni%, Servers, ServerList IniCheck("ServerList") ;For Testing ;MsgBox, IP: %MailServerIP%`nFrom: %MailFrom%`nTo: %MailTo%`nCC: %MailCC%`nMailUsername=%MailUsername%`nMailPassword=%MailPassword%`n`nFreq: %Frequency%`nFailures: %Failures%`n`nServers: %ServerList% ;MsgBox, MailUsername before decryption RC4: %RC4MailUsername%`nMailPassword before decryption RC4: %RC4MailPassword% ; For testing, enabled MailUsername := RC4hex2txt(RC4MailUsername,RC4Pass) MailPassword := RC4hex2txt(RC4MailPassword,RC4Pass) ;MsgBox, MailUsername after decryption RC4: %MailUsername%`nMailPassword after decryptionRC4: %MailPassword% ; For testing, enabled Loop, Parse, ServerList, CSV { Server%A_Index% = %A_LoopField% Server%A_Index%Down = Server%A_Index%State = Up ServerCount++ ; MsgBox, % Server%A_Index% ; for testing } Frequency := 1000 * Frequency ; 1000 miliseconds in one second ; Setup timer for periodic checking of server status Settimer, ServerCheck, %Frequency% ; Construct tray menu ServerCheck: Loop, %ServerCount% { ServerStatus(Server%A_Index%,Server%A_Index%Down,Server%A_Index%State) } Return IniError: MsgBox, 16, %ScriptName% - Ini Error, There was a problem reading or creating the %ScriptIni% file. Please examine the %ScriptIni% file for errors. ExitApp TrayMenu: Menu, Tray, NoStandard ; Disable standard menu items Menu, Tray, Add, Show ini file, ShowIni ; Show ini file Menu, Tray, Add, Show log file, ShowLog ; Show log file Menu, Tray, Add, Restart, Restart ; Restart/Reload Script Menu, Tray, Add, Pause, Pause ; Pause Script Menu, Tray, Add, About %ScriptName%, About ; Show about info Menu, Tray, Add, Exit, Exit ; Terminate script Menu, Tray, Default, Show log file ; Sets the show log file option as default Return ; Show Log file ShowLog: Run, notepad %ScriptLog% Return ; Show Ini file ShowIni: Run, notepad %ScriptIni% Return ; Restart script Restart: Reload Return ; Pause script Pause: Pause Return ; About info About: MsgBox, 64, %ScriptName%, %ScriptName%`, %ScriptVersion%`n%ScriptDate% Return ; Terminate script Exit: ExitApp ; Functions================================================================ ; Function to check if INI variables read correctly IniCheck(Field) { Global If %Field% = ERROR { MsgBox, 16, %ScriptName% - Ini Error, Unable to read Ini %Field%. GoSub, IniError } } ; Logging Function Log(Message) { Global ScriptLog FormatTime TimeString,, yyyy-MM-dd HH:mm:ss FileAppend, %TimeString% - %Message%`n, %A_ScriptDir%\%ScriptLog% } ; Email Notification Function Notify(Message) { Global MailTo,MailCC,MailFrom,MailAltFrom,MailServerIP,MailUsername,MailPassword FormatTime TimeString,, yyyy-MM-dd HH:mm:ss If MailCC = MailCCString = Else MailCCString = -c %MailCC% If MailAltFrom = MailAltFromString = Else MailAltFromString = -from %MailAltFrom% RunWait %A_Scriptdir%\blat\blat.exe ""- -to %MailTo% %MailCCString% -s "Server Alert" -body "%TimeString% - %Message%" -server %MailServerIP% -f %MailFrom% -u %MailUsername% -pw %MailPassword% %MailAltFromString% -q"", ,Hide Message = %Message% - Notification Sent Log(Message) } RC4txt2hex(Data,Pass) { Format := A_FormatInteger SetFormat Integer, Hex b := 0, j := 0 VarSetCapacity(Result,StrLen(Data)*2) Loop 256 { a := A_Index - 1 Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1)) sBox%a% := a } Loop 256 { a := A_Index - 1 b := b + sBox%a% + Key%a% & 255 T := sBox%a% sBox%a% := sBox%b% sBox%b% := T } Loop Parse, Data { i := A_Index & 255 j := sBox%i% + j & 255 k := sBox%i% + sBox%j% & 255 Result .= SubStr(Asc(A_LoopField)^sBox%k%, -1, 2) } StringReplace Result, Result, x, 0, All SetFormat Integer, %Format% Return Result } RC4hex2txt(Data,Pass) { b := 0, j := 0, x := "0x" VarSetCapacity(Result,StrLen(Data)//2) Loop 256 { a := A_Index - 1 Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1)) sBox%a% := a } Loop 256 { a := A_Index - 1 b := b + sBox%a% + Key%a% & 255 T := sBox%a% sBox%a% := sBox%b% sBox%b% := T } Loop % StrLen(Data)//2 { i := A_Index & 255 j := sBox%i% + j & 255 k := sBox%i% + sBox%j% & 255 Result .= Chr((x . SubStr(Data,2*A_Index-1,2)) ^ sBox%k%) } Return Result } ; Function to actually check server status ServerStatus(Server,ByRef ServerDown,ByRef ServerState) { Global Failures Target = /Repeat=1 /Timeout=10 %Server% RunWait, %A_ScriptDir%\Alive\alive.exe %Target%, , Hide ; MsgBox, %Server% errorlevel is %Errorlevel% ; for testing If Errorlevel = 0 { ; MsgBox, %Server% is up ; for testing If ServerState = Down { ServerState = Up ; Resets the ServerState if it was marked Down LogMessage = %Server% current ServerState: %ServerState%, after %ServerDown% failures. If ServerDown >= %Failures% ; MsgBox, Text Message that its back up ; for testing Notify(LogMessage) Else Log(LogMessage) ServerDown = ; clears the timeout count in case there was any on it } } Else If Errorlevel = 1 ErrorMessage = Request timed out ; ERRORLEVEL 1 Else If Errorlevel = 2 ErrorMessage = Destination host unreachable ; ERRORLEVEL 2 Else If Errorlevel = 3 ErrorMessage = Destination network unreachable ; ERRORLEVEL 3 Else If Errorlevel = 4 ErrorMessage = Destination protocol unreachable ; ERRORLEVEL 4 Else If Errorlevel = 5 ErrorMessage = Destination port unreachable ; ERRORLEVEL 5 Else If Errorlevel = 6 ErrorMessage = Hardware error ; ERRORLEVEL 6 Else If Errorlevel = 7 ErrorMessage = TTL expired in transit ; ERRORLEVEL 7 Else If Errorlevel = 8 ErrorMessage = Bad Destination ; ERRORLEVEL 8 Else ErrorMessage = Other errors ; ERRORLEVEL 255 If Errorlevel > 0 { ServerDown++ ; increments up the timeout count ServerState = Down LogMessage = %Server% not responding - %ErrorMessage% (%ServerDown%), ServerState: %ServerState% If ServerDown = %Failures% Notify(LogMessage) ; Log(LogMessage) ; for testing ; MsgBox, %Server% is really down! %LogMessage% ; for testing Else Log(LogMessage) ; MsgBox, %LogMessage% ; for testing } }Edit: Added new link to Alive 1.2 in the changelog.