cherdeg Posted October 21, 2009 Posted October 21, 2009 (edited) Hello Community,Once again I don't understand...why would this function return fewer hosts as "online" as there are in reality? I have an array of 8 IPs which are all online on the LAN. Microsoft's ping returns every single one correctly as online. The function below returns only 3 of them - why?expandcollapse popup#include <Constants.au3> #include <Array.au3> Local $s_MailRelayFQDN = "google.com" ;~ Local $s_MailRelayFQDN = "yahoo.com" ; try this instead...3 IPs ;~ Local $s_MailRelayFQDN = "microsoft.com" ; or this...2 IPs ;~ Local $s_MailRelayFQDN = "google.de" ; or this...3 IPs ;~ Local $s_MailRelayFQDN = "vmware.com" ; or this...1 IP Local $a_IPs = _LookupIPs($s_MailRelayFQDN) _ArrayDisplay($a_IPs) $a_IPsChecked = _CheckOnlineStatus($a_IPs) $a_OnlineIPs = $a_IPsChecked[0] _ArrayDisplay($a_OnlineIPs) ; Function Name _LookupIPs() ; ================================================================================================== ; ; Function Name: _LookupIPs() ; ; Description: Gets the IPs of a given FQDN ; ; Parameter(s): $s_FQDN ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): An array containing the IP(s) resolved for the given FQDN ; ; Author(s): cs/IT solutions ; ; ================================================================================================== Func _LookupIPs($s_FQDN) ; Setup and execute the command and fetch the STDout-data it produces $s_STDoutData = _RunReadStd("nslookup " & $s_FQDN, 0, @WorkingDir, 0, 1, @LF) ; Put the data to an array $a_tmp = StringSplit($s_STDoutData, @CRLF, 2) ; Delete the unneeded first 3 records For $i=1 To 3 _ArrayDelete($a_tmp, 0) Next ; Add all records to a new string; remove the words "Address" or "Addresses" Local $s_tmp For $i=0 To UBound($a_tmp) -1 $s_tmp &= StringReplace(StringReplace(StringStripWS($a_tmp[$i], 8), "Address:", ""), "Addresses:", "") If $i < UBound($a_tmp) -1 Then $s_tmp &= "," Next ; Split the string to an array $a_IPs = StringSplit($s_tmp, ",", 2) ; Return the array Return $a_IPs EndFunc ;==>_LookupIPs ; Function Name _CheckOnlineStatus() ; ================================================================================================== ; ; Function Name: _CheckOnlineStatus() ; ; Description: Checks if a host is online or not ; ; Parameter(s): $a_Hostnames ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): Two arrays containing: ; a) the hostnames of the hosts that are online ; b) the hostnames of the hosts that are offline ; ; Author(s): Manadar ; ; ================================================================================================== Func _CheckOnlineStatus($a_Hostnames) ; Copy the array of hostnames to a temporary one (in a loop arrays are read-only <== This is not true) Local $a_tmpOnHosts[1] Local $a_tmpOffHosts[1] ; Loop reversely one by one through the original array of hostnames For $i_i = 0 To UBound($a_Hostnames) - 1 ; Ping the current host to see if it is online ConsoleWrite("Ping: " & $a_Hostnames[$i_i] & @CRLF) $roundTrip = _Ping($a_Hostnames[$i_i]) If @error Then ConsoleWrite("Offline" & @CRLF) ; It's offline, add it to a list of offline hosts _ArrayAdd($a_tmpOffHosts, $a_Hostnames[$i_i]) Else ConsoleWrite("Online" & @CRLF) ; It's online, add it to a list of online hosts _ArrayAdd($a_tmpOnHosts, $a_Hostnames[$i_i]) EndIf Next _ArrayDelete($a_tmpOnHosts, 0) _ArrayDelete($a_tmpOffHosts, 0) ; Save both the temporary arrays to a transport array... Local $a_Hosts[2] $a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts ; $a_tmpOnHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; $a_tmpOffHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; ...return the transport array back to main() Return $a_Hosts EndFunc ;==>_CheckOnlineStatus ; Function Name _Ping() ; ================================================================================================== ; ; Function Name: _RunReadStd() ; ; Description: Pings a specified host address or IP address with a set number attempts and ; a set timeout ; ; Parameter(s): $ipOrHostName, $numAttempts = 2, $timeOut = 100 ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): Success: Returns the roundtrip (> 0) ; Failure: Returns 0 and sets @error to 1 ; ; Author(s): Manadar ; ; ================================================================================================== Func _Ping($ipOrHostName, $numAttempts = 2, $timeOut = 100) For $attempt = 0 To $numAttempts $roundTrip = Ping($ipOrHostName, $timeOut) $err = @error ConsoleWrite("@error:" & $err & @CRLF & "ret: " & $roundTrip & @CRLF) If Not $err Then Return $roundTrip EndIf Next Return SetError(1, 0, 0) EndFunc ;==>_Ping ; Function Name _RunReadStd() ; ================================================================================================== ; ; Function Name: _RunReadStd() ; ; Description:: Run a specified command, and return the Exitcode, StdOut text and ; StdErr text from from it. StdOut and StdErr are @tab delimited, ; with blank lines removed. ; ; Parameter(s): $doscmd: the actual command to run, same as used with Run command ; $timeoutSeconds: maximum execution time in seconds, optional, default: 0 (wait forever), ; $workingdir: directory in which to execute $doscmd, optional, default: @ScriptDir ; $flag: show/hide flag, optional, default: @SW_HIDE ; $sDelim: stdOut and stdErr output deliminter, optional, default: @TAB ; $nRetVal: return single item from function instead of array, optional, default: -1 (return array) ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): An array with three values, Exit Code, StdOut and StdErr ; ; Author(s): lod3n ; (Thanks to mrRevoked for delimiter choice and non array return selection) ; (Thanks to mHZ for _ProcessOpenHandle() and _ProcessGetExitCode()) ; (MetaThanks to DaveF for posting these DllCalls in Support Forum) ; (MetaThanks to JPM for including CloseHandle as needed) ; ; ================================================================================================== Func _RunReadStd($doscmd, $timeoutSeconds = 0, $workingdir = @ScriptDir, $flag = @SW_HIDE, $nRetVal = -1, $sDelim = @TAB) Local $aReturn, $i_Pid, $h_Process, $i_ExitCode, $sStdOut, $sStdErr, $runTimer Dim $aReturn[3] ; run process with StdErr and StdOut flags $runTimer = TimerInit() $i_Pid = Run($doscmd, $workingdir, $flag, 6) ; 6 = $STDERR_CHILD+$STDOUT_CHILD ; Get process handle Sleep(100) ; or DllCall may fail - experimental $h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $i_Pid) ; create tab delimited string containing StdOut text from process $aReturn[1] = "" $sStdOut = "" While 1 $sStdOut &= StdoutRead($i_Pid) If @error Then ExitLoop WEnd $sStdOut = StringReplace($sStdOut, @CR, @TAB) $sStdOut = StringReplace($sStdOut, @LF, @TAB) $aStdOut = StringSplit($sStdOut, @TAB, 1) For $i = 1 To $aStdOut[0] $aStdOut[$i] = StringStripWS($aStdOut[$i], 3) If StringLen($aStdOut[$i]) > 0 Then $aReturn[1] &= $aStdOut[$i] & $sDelim EndIf Next $aReturn[1] = StringTrimRight($aReturn[1], 1) ; create tab delimited string containing StdErr text from process $aReturn[2] = "" $sStdErr = "" While 1 $sStdErr &= StderrRead($i_Pid) If @error Then ExitLoop WEnd $sStdErr = StringReplace($sStdErr, @CR, @TAB) $sStdErr = StringReplace($sStdErr, @LF, @TAB) $aStderr = StringSplit($sStdErr, @TAB, 1) For $i = 1 To $aStderr[0] $aStderr[$i] = StringStripWS($aStderr[$i], 3) If StringLen($aStderr[$i]) > 0 Then $aReturn[2] &= $aStderr[$i] & $sDelim EndIf Next $aReturn[2] = StringTrimRight($aReturn[2], 1) ; kill the process if it exceeds $timeoutSeconds If $timeoutSeconds > 0 Then If TimerDiff($runTimer) / 1000 > $timeoutSeconds Then ProcessClose($i_Pid) EndIf EndIf ; fetch exit code and close process handle If IsArray($h_Process) Then Sleep(100) ; or DllCall may fail - experimental $i_ExitCode = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', 0) If IsArray($i_ExitCode) Then $aReturn[0] = $i_ExitCode[2] Else $aReturn[0] = -1 EndIf Sleep(100) ; or DllCall may fail - experimental DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process[0]) Else $aReturn[0] = -2 EndIf ; return single item if correctly specified with with $nRetVal If $nRetVal <> -1 And $nRetVal >= 0 And $nRetVal <= 2 Then Return $aReturn[$nRetVal] ; return array with exit code, stdout, and stderr Return $aReturn EndFunc ;==>_RunReadStdPlease help; I can't see any mistakes (maybe I'm blind by now).Best Regards,ChrisEDIT-1: Corrected the source to regard water's advice.EDIT-2: Corrected the comments in the source to regard Manadar's advice.EDIT-3: Replaced the source with the one from #7 Edited October 28, 2009 by cherdeg
water Posted October 21, 2009 Posted October 21, 2009 Because when a host can not be reached on the first try but on the second - then it is not added to $a_tmpOnHosts My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki Â
cherdeg Posted October 22, 2009 Author Posted October 22, 2009 (edited) Because when a host can not be reached on the first try but on the second - then it is not added to $a_tmpOnHostsOkay, you made a point: I corrected that. But that does not seem to be causing the problem - I played with the timeout values and set all of them to 5000 and even higher. The result was exactly the same, 3 of 8 came back as online... Again: Every single host in the list is pingable by Microsoft's ping. Edited October 27, 2009 by cherdeg
jvanegmond Posted October 22, 2009 Posted October 22, 2009 (edited) Your function seems to work fine, or I have accidentally fixed it while playing.Note that you can't do this (this may be is probably going wrong):Dim $a[1] = ["Hello world!!"] Dim $b[1] = [$a] MsgBox(0, "", $b[0][0]) ; FAILS!! $c = $b[0] MsgBox(0, "", $c[0])expandcollapse popup; The function _CheckOnlineStatus() splits an array of hostnames or IPs into two arrays: ; One for the Online-Hosts, another for the Offline-Hosts. ; ================================================================================================== #include <Array.au3> Local $testIP[3] = ["127.0.0.1", "128.0.0.1", "129.0.0.1"] $arr = _CheckOnlineStatus($testIP) $online = $arr[0] _ArrayDisplay($online) $offline = $arr[1] _ArrayDisplay($offline) Func _CheckOnlineStatus($a_Hostnames) ; Copy the array of hostnames to a temporary one (in a loop arrays are read-only <== This is not true) Local $a_tmpOnHosts[1] Local $a_tmpOffHosts[1] ; Loop reversely one by one through the original array of hostnames For $i_i = 0 to UBound($a_Hostnames) -1 ; Ping the current host to see if it is online $roundTrip = _Ping($a_Hostnames[$i_i]) If @error Then ; It's offline, add it to a list of offline hosts _ArrayAdd($a_tmpOffHosts, $a_Hostnames[$i_i]) Else ; It's online, add it to a list of online hosts _ArrayAdd($a_tmpOnHosts, $a_Hostnames[$i_i]) EndIf Next _ArrayDelete($a_tmpOnHosts, 0) _ArrayDelete($a_tmpOffHosts, 0) ; Save both the temporary arrays to a transport array... Local $a_Hosts[2] $a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts ; $a_tmpOnHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; $a_tmpOffHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; ...return the transport array back to main() Return $a_Hosts EndFunc ;==>_CheckOnlineStatus ; Pings a specified host address or IP address with a set number attempts and a set timeout ; Success: Returns the roundtrip (> 0) ; Failure: Returns 0 and sets @error to 1 Func _Ping($ipOrHostName, $numAttempts = 2, $timeOut = 100) For $attempt = 0 to $numAttempts-1 $roundTrip = Ping($ipOrHostName, $timeOut) If Not @error Then Return $roundTrip EndIf Next Return SetError(1, 0, 0) EndFunc Edited October 22, 2009 by Manadar github.com/jvanegmond
cherdeg Posted October 22, 2009 Author Posted October 22, 2009 (edited) Hey Manadar, sorry, but what are you talking of?This works perfect.:$a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts $a_tmpOnHosts = 0 $a_tmpOffHosts = 0 Return $a_HostsBoth arrays are 1st copied to the "transport array", 2nd deleted and 3rd returned. Or why else would that (outside the function) work anyway?:_ArrayDisplay($a_Hosts[0], "BLA")Of course it is clear for me that MsgBox() can't display arrays. But that's not the point; logically the on-/off-arrays are extracted from the "transport array" before they are used further.And, again of course: In a for...next loop not all arrays are read only. But the one the loop cycles through is.Last but not least pinging three local IPs does not prove or invalidate anything. Edited October 22, 2009 by cherdeg
jvanegmond Posted October 22, 2009 Posted October 22, 2009 Nice job on misunderstanding me and then trying to start an argument. You officially qualify as an internet troll. Print a certificate, and lose the attitude. Now that's out of the way... This works perfect.: $a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts $a_tmpOnHosts = 0 $a_tmpOffHosts = 0 Return $a_Hosts Both arrays are 1st copied to the "transport array", 2nd deleted and 3rd returned. Or why else would that (outside the function) work anyway?:_ArrayDisplay($a_Hosts[0], "BLA") All I said was that you don't have to destroy a variable that holds an array by assigning 0 to it. Once a local variable leaves the current scope, they are destroyed automatically. It's not necessary to delete an array by assigning it 0, in this case. Of course it is clear for me that MsgBox() can't display arrays. But that's not the point; logically the on-/off-arrays are extracted from the "transport array" before they are used further.In this example: Dim $a[1] = ["Hello world!!"] Dim $b[1] = [$a] MsgBox(0, "", $b[0][0]) ; FAILS!! In some languages, the variable $b would be a two dimensional array. If that's the case you can retrieve the element by doing [0][0], this is something AutoIt doesn't support: But a lot of other languages do. Since you have failed to provide a fully functional reproduction script, I have to guess at some parts which may be going wrong, this was one of them. And, again of course: In a for...next loop not all arrays are read only. But the one the loop cycles through is. Oh? Local $a[3] = [1, 2, 3] Local $b[3] = [4, 5, 6] ; Array is 1 2 3 For $i = 0 to 2 MsgBox(0, "", $a[$i]) Next For $i = 0 to 2 $a[$i] = 4 - $a[$i] Next ; Array is now 3 2 1 For $i = 0 to 2 MsgBox(0, "", $a[$i]) Next For $i = 0 to 2 $a = $b ; just an example Next ; Array is now 4 5 6 For $i = 0 to 2 MsgBox(0, "", $a[$i]) Next Last but not least pinging three local IPs does not prove or invalidate anything. It proves that the rest of the code is fine, and that you can focus on analyzing the functionality of "Ping". This is an important fact to establish, because now you can write a reproducer as simple as: $ret = Ping("123.123.123.123") ConsoleWrite("@error: " & @error & @CRLF & "Ret: " & $ret & @CRLF) Since this works as expected, you might have another look at your original script (which also works). I have extended the working example with some debugging: expandcollapse popup; The function _CheckOnlineStatus() splits an array of hostnames or IPs into two arrays: ; One for the Online-Hosts, another for the Offline-Hosts. ; ================================================================================================== #include <Array.au3> Local $testIP[4] = ["www.google.com", "www.microsoft.com", "www.msn.com", "123.123.123.123"] $arr = _CheckOnlineStatus($testIP) $online = $arr[0] _ArrayDisplay($online, "Online") $offline = $arr[1] _ArrayDisplay($offline, "Offline") Func _CheckOnlineStatus($a_Hostnames) ; Copy the array of hostnames to a temporary one (in a loop arrays are read-only <== This is not true) Local $a_tmpOnHosts[1] Local $a_tmpOffHosts[1] ; Loop reversely one by one through the original array of hostnames For $i_i = 0 to UBound($a_Hostnames) -1 ; Ping the current host to see if it is online ConsoleWrite("Ping: " & $a_Hostnames[$i_i] & @CRLF) $roundTrip = _Ping($a_Hostnames[$i_i]) If @error Then ConsoleWrite("Offline" & @CRLF) ; It's offline, add it to a list of offline hosts _ArrayAdd($a_tmpOffHosts, $a_Hostnames[$i_i]) Else ConsoleWrite("Online" & @CRLF) ; It's online, add it to a list of online hosts _ArrayAdd($a_tmpOnHosts, $a_Hostnames[$i_i]) EndIf Next _ArrayDelete($a_tmpOnHosts, 0) _ArrayDelete($a_tmpOffHosts, 0) ; Save both the temporary arrays to a transport array... Local $a_Hosts[2] $a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts ; $a_tmpOnHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; $a_tmpOffHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; ...return the transport array back to main() Return $a_Hosts EndFunc ;==>_CheckOnlineStatus ; Pings a specified host address or IP address with a set number attempts and a set timeout ; Success: Returns the roundtrip (> 0) ; Failure: Returns 0 and sets @error to 1 Func _Ping($ipOrHostName, $numAttempts = 2, $timeOut = 100) For $attempt = 0 to $numAttempts $roundTrip = Ping($ipOrHostName, $timeOut) $err = @error ConsoleWrite("@error:" & $err & @CRLF & "ret: " & $roundTrip & @CRLF) If Not $err Then Return $roundTrip EndIf Next Return SetError(1, 0, 0) EndFunc github.com/jvanegmond
cherdeg Posted October 23, 2009 Author Posted October 23, 2009 (edited) Nice job on misunderstanding me and then trying to start an argument. You officially qualify as an internet troll. Print a certificate, and lose the attitude.Thanks for the flowers. You made me cry. Probably you screwed up my whole weekend, I'll need weeks to recover from that. I hope you can live with that. From the helpfile ("Dim"): To erase an array (maybe because it is a large global array and you want to free the memory), simply assign a single value to it: $array = 0 This will free the array and convert it back to the single value of 0.Probably I should add to my sig that I am no programmer at all and use AutoIt for about a year (for phun, not as a pro). So basically I don't think about scopes of variables if I don't need to, please excuse that slothfulness. I just do what's in the helpfile. If my code is not perfect but works the way I need it to, I'm quite comfortable with that. From the helpfile ("For...In...Next"): Autoit Array's are read-only when using For...In. While you can assign the variable inside the For...In loop a value, this change is not reflected in the array itself. To modify the contents of an array during enumeration use a For...To loop.Yes, I know. I don't use a For...In...Next-loop. But I did in an earlier version of the function. Currently I am quite ill and can't concentrate as usual and forgot about it. So basically both our statements contain...something. This: Dim $a[1] = ["Hello world!!"] Dim $b[1] = [$a] MsgBox(0, "", $b[0][0]) ; FAILS!!...never was a question in doubt. I well know that $b[1] nests array $a. So the code below is my whole script in its current state (please note that I've copied the code from your last post without modifying anything): expandcollapse popup#include <Constants.au3> #include <Array.au3> Local $s_MailRelayFQDN = "google.com" ;~ Local $s_MailRelayFQDN = "yahoo.com" ; try this instead...3 IPs ;~ Local $s_MailRelayFQDN = "microsoft.com" ; or this...2 IPs ;~ Local $s_MailRelayFQDN = "google.de" ; or this...3 IPs ;~ Local $s_MailRelayFQDN = "vmware.com" ; or this...1 IP Local $a_IPs = _LookupIPs($s_MailRelayFQDN) _ArrayDisplay($a_IPs) $a_IPsChecked = _CheckOnlineStatus($a_IPs) $a_OnlineIPs = $a_IPsChecked[0] _ArrayDisplay($a_OnlineIPs) ; Function Name _LookupIPs() ; ================================================================================================== ; ; Function Name: _LookupIPs() ; ; Description: Gets the IPs of a given FQDN ; ; Parameter(s): $s_FQDN ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): An array containing the IP(s) resolved for the given FQDN ; ; Author(s): cs/IT solutions ; ; ================================================================================================== Func _LookupIPs($s_FQDN) ; Setup and execute the command and fetch the STDout-data it produces $s_STDoutData = _RunReadStd("nslookup " & $s_FQDN, 0, @WorkingDir, 0, 1, @LF) ; Put the data to an array $a_tmp = StringSplit($s_STDoutData, @CRLF, 2) ; Delete the unneeded first 3 records For $i=1 To 3 _ArrayDelete($a_tmp, 0) Next ; Add all records to a new string; remove the words "Address" or "Addresses" Local $s_tmp For $i=0 To UBound($a_tmp) -1 $s_tmp &= StringReplace(StringReplace(StringStripWS($a_tmp[$i], 8), "Address:", ""), "Addresses:", "") If $i < UBound($a_tmp) -1 Then $s_tmp &= "," Next ; Split the string to an array $a_IPs = StringSplit($s_tmp, ",", 2) ; Return the array Return $a_IPs EndFunc ;==>_LookupIPs ; Function Name _CheckOnlineStatus() ; ================================================================================================== ; ; Function Name: _CheckOnlineStatus() ; ; Description: Checks if a host is online or not ; ; Parameter(s): $a_Hostnames ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): Two arrays containing: ; a) the hostnames of the hosts that are online ; b) the hostnames of the hosts that are offline ; ; Author(s): Manadar ; ; ================================================================================================== Func _CheckOnlineStatus($a_Hostnames) ; Copy the array of hostnames to a temporary one (in a loop arrays are read-only <== This is not true) Local $a_tmpOnHosts[1] Local $a_tmpOffHosts[1] ; Loop reversely one by one through the original array of hostnames For $i_i = 0 To UBound($a_Hostnames) - 1 ; Ping the current host to see if it is online ConsoleWrite("Ping: " & $a_Hostnames[$i_i] & @CRLF) $roundTrip = _Ping($a_Hostnames[$i_i]) If @error Then ConsoleWrite("Offline" & @CRLF) ; It's offline, add it to a list of offline hosts _ArrayAdd($a_tmpOffHosts, $a_Hostnames[$i_i]) Else ConsoleWrite("Online" & @CRLF) ; It's online, add it to a list of online hosts _ArrayAdd($a_tmpOnHosts, $a_Hostnames[$i_i]) EndIf Next _ArrayDelete($a_tmpOnHosts, 0) _ArrayDelete($a_tmpOffHosts, 0) ; Save both the temporary arrays to a transport array... Local $a_Hosts[2] $a_Hosts[0] = $a_tmpOnHosts $a_Hosts[1] = $a_tmpOffHosts ; $a_tmpOnHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; $a_tmpOffHosts = 0 <== When these fall out of the current scope (EndFunc) they are destroyed automatically ; ...return the transport array back to main() Return $a_Hosts EndFunc ;==>_CheckOnlineStatus ; Function Name _Ping() ; ================================================================================================== ; ; Function Name: _RunReadStd() ; ; Description: Pings a specified host address or IP address with a set number attempts and ; a set timeout ; ; Parameter(s): $ipOrHostName, $numAttempts = 2, $timeOut = 100 ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): Success: Returns the roundtrip (> 0) ; Failure: Returns 0 and sets @error to 1 ; ; Author(s): Manadar ; ; ================================================================================================== Func _Ping($ipOrHostName, $numAttempts = 2, $timeOut = 100) For $attempt = 0 To $numAttempts $roundTrip = Ping($ipOrHostName, $timeOut) $err = @error ConsoleWrite("@error:" & $err & @CRLF & "ret: " & $roundTrip & @CRLF) If Not $err Then Return $roundTrip EndIf Next Return SetError(1, 0, 0) EndFunc ;==>_Ping ; Function Name _RunReadStd() ; ================================================================================================== ; ; Function Name: _RunReadStd() ; ; Description:: Run a specified command, and return the Exitcode, StdOut text and ; StdErr text from from it. StdOut and StdErr are @tab delimited, ; with blank lines removed. ; ; Parameter(s): $doscmd: the actual command to run, same as used with Run command ; $timeoutSeconds: maximum execution time in seconds, optional, default: 0 (wait forever), ; $workingdir: directory in which to execute $doscmd, optional, default: @ScriptDir ; $flag: show/hide flag, optional, default: @SW_HIDE ; $sDelim: stdOut and stdErr output deliminter, optional, default: @TAB ; $nRetVal: return single item from function instead of array, optional, default: -1 (return array) ; ; Requirement(s): AutoIt 3.2.10.0 ; ; Return Value(s): An array with three values, Exit Code, StdOut and StdErr ; ; Author(s): lod3n ; (Thanks to mrRevoked for delimiter choice and non array return selection) ; (Thanks to mHZ for _ProcessOpenHandle() and _ProcessGetExitCode()) ; (MetaThanks to DaveF for posting these DllCalls in Support Forum) ; (MetaThanks to JPM for including CloseHandle as needed) ; ; ================================================================================================== Func _RunReadStd($doscmd, $timeoutSeconds = 0, $workingdir = @ScriptDir, $flag = @SW_HIDE, $nRetVal = -1, $sDelim = @TAB) Local $aReturn, $i_Pid, $h_Process, $i_ExitCode, $sStdOut, $sStdErr, $runTimer Dim $aReturn[3] ; run process with StdErr and StdOut flags $runTimer = TimerInit() $i_Pid = Run($doscmd, $workingdir, $flag, 6) ; 6 = $STDERR_CHILD+$STDOUT_CHILD ; Get process handle Sleep(100) ; or DllCall may fail - experimental $h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $i_Pid) ; create tab delimited string containing StdOut text from process $aReturn[1] = "" $sStdOut = "" While 1 $sStdOut &= StdoutRead($i_Pid) If @error Then ExitLoop WEnd $sStdOut = StringReplace($sStdOut, @CR, @TAB) $sStdOut = StringReplace($sStdOut, @LF, @TAB) $aStdOut = StringSplit($sStdOut, @TAB, 1) For $i = 1 To $aStdOut[0] $aStdOut[$i] = StringStripWS($aStdOut[$i], 3) If StringLen($aStdOut[$i]) > 0 Then $aReturn[1] &= $aStdOut[$i] & $sDelim EndIf Next $aReturn[1] = StringTrimRight($aReturn[1], 1) ; create tab delimited string containing StdErr text from process $aReturn[2] = "" $sStdErr = "" While 1 $sStdErr &= StderrRead($i_Pid) If @error Then ExitLoop WEnd $sStdErr = StringReplace($sStdErr, @CR, @TAB) $sStdErr = StringReplace($sStdErr, @LF, @TAB) $aStderr = StringSplit($sStdErr, @TAB, 1) For $i = 1 To $aStderr[0] $aStderr[$i] = StringStripWS($aStderr[$i], 3) If StringLen($aStderr[$i]) > 0 Then $aReturn[2] &= $aStderr[$i] & $sDelim EndIf Next $aReturn[2] = StringTrimRight($aReturn[2], 1) ; kill the process if it exceeds $timeoutSeconds If $timeoutSeconds > 0 Then If TimerDiff($runTimer) / 1000 > $timeoutSeconds Then ProcessClose($i_Pid) EndIf EndIf ; fetch exit code and close process handle If IsArray($h_Process) Then Sleep(100) ; or DllCall may fail - experimental $i_ExitCode = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', 0) If IsArray($i_ExitCode) Then $aReturn[0] = $i_ExitCode[2] Else $aReturn[0] = -1 EndIf Sleep(100) ; or DllCall may fail - experimental DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process[0]) Else $aReturn[0] = -2 EndIf ; return single item if correctly specified with with $nRetVal If $nRetVal <> -1 And $nRetVal >= 0 And $nRetVal <= 2 Then Return $aReturn[$nRetVal] ; return array with exit code, stdout, and stderr Return $aReturn EndFunc ;==>_RunReadStd Result: I can ping all the IPs (external and internal targets) if I use Microsoft's ping from my XP system's command line. If I use the script, I today get 4 of 8 hosts for my internal FQDN, which, at least, is an improvement to the yesterday's 3. But I doubt it has something to do with your/my code. For the external hosts as google.com I sometimes get one pingable host but most times it states that none was online. What now? Edited October 27, 2009 by cherdeg
lordicast Posted October 23, 2009 Posted October 23, 2009 Nice job on misunderstanding me and then trying to start an argument. You officially qualify as an internet troll. Print a certificate, and lose the attitude.Where would one get these troll certificates? [Cheeky]Comment[/Cheeky]
cherdeg Posted October 26, 2009 Author Posted October 26, 2009 Hello, aahhh...I hoped so much that I'd return to office this morning and find sombody's perfect solution in this thread...'coz my problem still exists and I still lack of ideas how to start solving it. The code so far seems okay for me, but in my opinion AutoIt's ping() does not work as supposed. Best Regards, Chris
November Posted October 26, 2009 Posted October 26, 2009 Working fine to me! I added some internet hosts and corporate hosts, mixing unc and ip and all running smoothly! Check you DNS/host file. Cheers Old Scriptology Visual Ping 1.8 - Mass Ping Program with export to txt delimited. Desktop 2 RGB and YMCK - Pick a color in the desktop and get the RGB and YMCK code. Desktop 2 RGB - Pick a color in the desktop and get the RGB code. ShootIT 1.0 - Screen Capture full and partial screen [font="'Arial Black';"]Remember Remember The Fifth of November.[/font]
cherdeg Posted October 27, 2009 Author Posted October 27, 2009 (edited) Check you DNS/host file.Don't need to. You wonder why?Because I believe I wrote about 3 times in this thread, that I can ping all the host-IPs nslookup returns from the Windows command line without any problem. I emphasized the statements in my above posts for you. Only AutoIt's ping() is not able to see them online. That is the reason for this thread.Is this simple fact that hard to understand? Edited October 28, 2009 by cherdeg
ProgAndy Posted October 27, 2009 Posted October 27, 2009 (edited) NSLOOKUP IS NOT PINGtry ping from your command prompt, this should work the same way as ping in AutoIt Edit:There are servers who block ping-requests, but are still online. This is not the fault of AutoIt, but the configuration of the servers you want to ping. Edited October 27, 2009 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes
cherdeg Posted October 27, 2009 Author Posted October 27, 2009 (edited) NSLOOKUP IS NOT PINGtry ping from your command prompt, this should work the same way as ping in AutoIt Edit:There are servers who block ping-requests, but are still online. This is not the fault of AutoIt, but the configuration of the servers you want to ping.You also can't read, hmmm? And, before posting, you don't drop even a quick look at the sources you're going to write about, hmmm?Would you please just try to assume that not everybody is a 12 year old girl (probably even most of them would know that nslookup is not ping)?I mean, hey, WTF? I use nslookup to get the IPs of certain FQDNs. In case of "google.com" the IPs 74.125.45.100, 74.125.53.100, 74.125.67.100 are returned (at least from my location). Pinging these IPs one after the other from command line shows that every single host is online. If I set $s_MailRelayFQDN to "google.com", the returned array contains exactly these IPs. Manadar's function "_Ping" which uses AutoIt's ping() returns all hosts as offline; I have the same result with all my tries. Edited October 27, 2009 by cherdeg
jvanegmond Posted October 27, 2009 Posted October 27, 2009 (edited) You have quite a problem on your hands, which I can understand explains for the attitude. It's still not a very nice attitude when you're coming asking for help. Can you try the script on another machine? Try installing the latest AutoIt, etc. I believe for everyone who have tried this it is working as expected, except yourself.. Also try writing a small reproducer and try it on several machines: (Change the address to one that fails, which you are expecting to succeed) $a = Ping("10.10.10.10") ConsoleWrite($a & @CRLF & @error & @CRLF) Edited October 27, 2009 by Manadar github.com/jvanegmond
ProgAndy Posted October 27, 2009 Posted October 27, 2009 (edited) You also can't read, hmmm? And, before posting, you don't drop even a quick look at the sources you're going to write about, hmmm?Oh, sorry, i misunderstood you underlined text. I read a full stop between host-IPs and nslookup. Edited October 27, 2009 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes
cherdeg Posted October 27, 2009 Author Posted October 27, 2009 (edited) the attitude Yeah, I'm quite irritated by now. I think the least one can await from any guy willing to help is that he reads before he posts completely unqualified comments only wasting everybody's time. You and I, we had some misunderstandings, but I can see you're really trying to help - thank you for that! Okay, so I compiled my source as as cli app and tested it on four systems. On each the Windows firewall is off and there is no additional firewall installed. The script is compiled with the latest version of AutoIT (v3.3.0.0). The results are the same on every machine: Ping: 74.125.45.100 @error:1 ret: 0 @error:1 ret: 0 @error:1 ret: 0 Offline Ping: 74.125.53.100 @error:1 ret: 0 @error:1 ret: 0 @error:1 ret: 0 Offline Ping: 74.125.67.100 @error:1 ret: 0 @error:1 ret: 0 @error:1 ret: 0 Offline I don't want to look as ignorant as others, so I also tried your two lines of code on the same machines. I modified them a bit, which shouldn't impact the basic funtionality (the IPs belong to google.com):#AutoIt3Wrapper_Change2CUI=y local $array[3] = ["74.125.45.100", "74.125.53.100", "74.125.67.100"] for $i=0 to UBound($array) -1 $a = ping($array[$i]) consolewrite("Return-Value: " & $a & @CRLF & "@Error-Value: " & @error & @CRLF) next The result is, again, the same:Return-Value: 0 @Error-Value: 1 Return-Value: 0 @Error-Value: 1 Return-Value: 0 @Error-Value: 1 And last but not least: all IPs are still pingable from all hosts' command line (Microsoft's ping). Edited October 28, 2009 by cherdeg
cherdeg Posted October 28, 2009 Author Posted October 28, 2009 I still have the same problem. Please again note that on four source-hosts everything is WORKING with Microsofts ping and NOT WORKING with AutoITs ping(). On none of the systems any kind of firewall or antivirus software is installed. A misconfiguration of the source hosts The problem clearly comes from AutoITs ping() function which reports hosts that are online as offline (Return 0, @error 1). Please prove me wrong.
jvanegmond Posted October 28, 2009 Posted October 28, 2009 (edited) I still have the same problem. Please again note that on four source-hosts everything is WORKING with Microsofts ping and NOT WORKING with AutoITs ping(). On none of the systems any kind of firewall or antivirus software is installed. A misconfiguration of the source hosts The problem clearly comes from AutoITs ping() function which reports hosts that are online as offline (Return 0, @error 1). Please prove me wrong.The only way we can prove you are wrong is by showing that it works, which it does, for everyone else at least. You're a special case.The simple solution would be to run the Microsoft ping command, and parse the outputs from command line.Some pointers:RunStdoutReadStringRegexpetc. Edited October 28, 2009 by Manadar github.com/jvanegmond
cherdeg Posted October 28, 2009 Author Posted October 28, 2009 (edited) Hi Manadar,so you tell me that this:#AutoIt3Wrapper_Change2CUI=y local $array[3] = ["74.125.45.100", "74.125.53.100", "74.125.67.100"] for $i=0 to UBound($array) -1 $a = ping($array[$i]) consolewrite("IP : " & $array[$i] & @CRLF & "Return-Value: " & $a & @CRLF & "@Error-Value: " & @error & @CRLF & @CRLF) next...returns three online hosts on your machine? You can see my result if you check the attached screenshot (hey, today one of the google.com's frontend hosts really is offline!). What could be a reason for this behaviour?I really need to use AutoIT's ping() due to the fact that Microsoft's counterpart is way to slow. I need to check about 400 hosts in acceptable time...so it would be really great to get that working. Edited October 28, 2009 by cherdeg
jvanegmond Posted October 28, 2009 Posted October 28, 2009 (edited) Yes, it does. The lower right left () shows the console output. Edited October 28, 2009 by Manadar github.com/jvanegmond
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now