Jump to content

Generate ip addresses based on format


jvanegmond
 Share

Recommended Posts

I couldn't figure out how to do this at first, and spent some sweat. "Never again!" I said to myself, and posted it on the forum.

This is how you should do it (simple method):

#include <Array.au3>

$routerList = _GetIpAddressList("192.168.0-2.0-1")
_ArrayDisplay($routerList)

$clientList = _GetIpAddressList("192.168.0-2.100-110")
_ArrayDisplay($clientList)

$randomTest = _GetIpAddressList("0-2.2-4.4-6.6-8")
_ArrayDisplay($randomTest)


Func _GetIpAddressList($ipFormat)
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")

    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i+1], "-") Then
            $m = StringSplit($ipSplit[$i+1],"-")
            $ipRange[$i][0] = $m[1]
            $ipRange[$i][1] = $m[2]
        Else
            $n = Number($ipSplit[$i+1])
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $result[$totalPermu], $i = 0

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $result[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next

    Return $result
EndFunc   ;==>_GetIpAddressList

This is what I wasted my time on the first time:

#include <Array.au3>

$routerList = _GetIpAddressList("192.168.0-2.0-1")
_ArrayDisplay($routerList)

$clientList = _GetIpAddressList("192.168.0-2.100-110")
_ArrayDisplay($clientList)

$randomTest = _GetIpAddressList("0-2.2-4.4-6.6-8")
_ArrayDisplay($randomTest)

Func _GetIpAddressList($ipFormat)
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")

    Local $ipDef[4], $totalPermu = 1, $curPart[4]

    For $i = 0 To 3
        $range = _GetIpAddressArray($ipSplit[$i + 1])
        $curPart[$i] = $range[0]
        $totalPermu *= $range[1] - $range[0] + 1
        $ipDef[$i] = $range
    Next

    Local $result[$totalPermu]

    $m = 0
    While 1
        $result[$m] = $curPart[0] & "." & $curPart[1] & "." & $curPart[2] & "." & $curPart[3]
        $m += 1

        $add = 1
        For $i = 3 To 0 Step -1
            If $add Then
                $n = _GetIpAddressAdder($ipDef[$i])
                $curPart[$i] = $n[0]
                $add = $n[1]
            EndIf
        Next

        If $add Then
            ExitLoop
        EndIf
    WEnd

    Return $result
EndFunc   ;==>_GetIpAddressList

Func _GetIpAddressAdder(ByRef $range)
    Local $ret[2] = [0, 0]
    $range[2] += 1
    If $range[2] > $range[1] Then
        $ret[1] = 1
        $range[2] = $range[0]
    EndIf
    $ret[0] = $range[2]
    Return $ret
EndFunc   ;==>_GetIpAddressAdder

Func _GetIpAddressArray($range)
    Local $ret[3]

    If StringInStr($range, "-") Then
        $lSplit = StringSplit($range, "-")
        $lStart = $lSplit[1]
        $lStop = $lSplit[2]
        $lCount = $lStop - $lStart + 1

        $ret[0] = $lStart
        $ret[1] = $lStop
        $ret[2] = $ret[0]
    Else
        $n = Number($range)
        $ret[0] = $n
        $ret[1] = $n
        $ret[2] = $n
    EndIf

    Return $ret
EndFunc   ;==>_GetIpAddressArray

Edited by Manadar
Link to comment
Share on other sites

I come into work today, and talk with my coworkers about this problem that I solved last night. I tell them I wanted to do it recursively, but failed that and did it sequentially which was much harder. I talk a bit about the problem and how complicated it was until someone says; That's just 4 For-Next loops.

I could punch myself in the face at that point. Last night I posed the restriction on myself of using a recursive method, meaning I couldn't use the 4 for-loops method, after losing interest in the recursive method I never reconsidered I could use the 4 for-loops method. I've now redone it, which took about 5 minutes.

Although, I guess the old code was nice too, because it's probably more ip v6 compatible. (ergo; Needs less changes.)

Link to comment
Share on other sites

I come into work today, and talk with my coworkers about this problem that I solved last night. I tell them I wanted to do it recursively, but failed that and did it sequentially which was much harder. I talk a bit about the problem and how complicated it was until someone says; That's just 4 For-Next loops.

I could punch myself in the face at that point.

That's the approach I was taking, but I couldn't think it through.

I'll punch you in the face though. Since it's your birthday, I'll let you off ;)

Edited by JamesBrooks
Link to comment
Share on other sites

So I got some time to mess around with this and I have to admit it was pretty fun. Here are some tweaks on the function to add some minimal error checking. Also, below that is a combination of the script you had in the other thread and the script you posted here. End result was a small network prober as you mentioned.

Func _GetIpAddressList($ipFormat)
    Local $aResult[1]
    $aResult[0] = 0
    
    If StringInStr(StringStripWS($ipFormat, 3), " ") Or StringInStr($ipFormat, ".", "", 4) Then Return $aResult
    
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")
    
    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i + 1], "-") Then
            If StringInStr($ipSplit[$i + 1], "-", "", 2) Then Return $aResult
            $m = StringSplit($ipSplit[$i +1 ],"-")
            For $i2 = 1 to $m[0] 
                If Number($m[$i2]) > 255 Then Return $aResult
                $ipRange[$i][$i2 - 1] = Number($m[$i2])
            Next
        Else
            $n = Number($ipSplit[$i + 1])
            If $n > 255 Then Return $aResult
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $aResult[$totalPermu + 1], $i = 1

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $aResult[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next
    
    $aResult[0] = $i - 1
    Return $aResult
EndFunc   ;==>_GetIpAddressList

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

AutoItSetOption("GUIOnEventMode", 1)

$hGUI = GUICreate("Alive", 348, 303, 190, 130)
$hGo = GUICtrlCreateButton("Go", 250, 8, 57, 25, 0)
$hInput = GUICtrlCreateInput("", 15, 10, 200)
$hList = GUICtrlCreateList("", 15, 64, 313, 193)
$hClear = GUICtrlCreateButton("Clear", 120, 272, 89, 25, 0)
GUICtrlSetOnEvent($hGo, "alive")
GUICtrlSetOnEvent($hClear, "clear")
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
GUICtrlSetState($hInput, $GUI_FOCUS)
GUISetState(@SW_SHOW)

While 1
    Sleep(50)
    If _IsPressed("0D") Then alive()
WEnd

Func alive()
    $sAddress = GUICtrlRead($hInput)
    
    If $sAddress = "" Then 
        MsgBox(0, "Error", "Input was null", 0, $hGUI)
        Return
    EndIf
    
    GUICtrlSetState($hGo, $GUI_DISABLE)
    GUICtrlSetState($hClear, $GUI_DISABLE)
    
    $aArray = _GetIpAddressList($sAddress)
    If $aArray[0] = 0 Then 
        MsgBox(0, "Error", "Input was incorrect. Check syntax.", 0, $hGUI)
        enableButtons()
        Return
    EndIf
    
    Local Const $MAX_PROCESS = 10 ; We spawn a maximum of 10 processes at once
    Local $aProcess[$MAX_PROCESS] ; An array to keep a reference to spawned processes, in the next loop we fill it with value 0
    For $i = 0 to UBound($aProcess) - 1
        $aProcess[$i] = 0
    Next
    
    Local $i = 1
    Local $iFinished = 1
    While True
        For $n = 0 to UBound($aProcess) - 1
            If ($i <> UBound($aArray) AND $aProcess[$n] == 0) Then ; Check if we need a spot, and there is an existing spot
                    $aProcess[$n] = _MSPing($aArray[$i])
                    $i += 1
            Else
                If ($aProcess[$n] <> 0 And _MSPingIsReady($aProcess[$n])) Then
                    
                    $sHostname = _MSPingGetHostname($aProcess[$n])
                    $sResult = _MSPingGetResult($aProcess[$n])
                    If ($sResult <> -1) Then
                        GUICtrlSetData($hList, $sHostname & " is alive " & $sResult & " milliseconds" & @CRLF)
                    Else
                        GUICtrlSetData($hList, $sHostname & " is dead" & @CRLF)
                    EndIf

                    ; Free up an empty space for the next address to Ping
                    $aProcess[$n] = 0
                        
                    $iFinished += 1 ; <=== New line
                    If ($iFinished == UBound($aArray)) Then ExitLoop 2 ; Return
                EndIf
            EndIf
        Next
        Sleep(50) ; Give existing ping commands some time to process the request
    WEnd
    
    enableButtons()
EndFunc

Func enableButtons()
    GUICtrlSetState($hGo, @SW_ENABLE)
    GUICtrlSetState($hClear, @SW_ENABLE)
EndFunc

Func clear()
    GUICtrlSetData($hList, "")
EndFunc

Func _GetIpAddressList($ipFormat)
    Local $aResult[1]
    $aResult[0] = 0
    
    If StringInStr(StringStripWS($ipFormat, 3), " ") Or StringInStr($ipFormat, ".", "", 4) Then Return $aResult
    
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")
    
    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i + 1], "-") Then
            If StringInStr($ipSplit[$i + 1], "-", "", 2) Then Return $aResult
            $m = StringSplit($ipSplit[$i +1 ],"-")
            For $i2 = 1 to $m[0] 
                If Number($m[$i2]) > 255 Then Return $aResult
                $ipRange[$i][$i2 - 1] = Number($m[$i2])
            Next
        Else
            $n = Number($ipSplit[$i + 1])
            If $n > 255 Then Return $aResult
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $aResult[$totalPermu + 1], $i = 1

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $aResult[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next
    
    $aResult[0] = $i - 1
    Return $aResult
EndFunc   ;==>_GetIpAddressList

Func _Exit()
    Exit
EndFunc

Func _MSPing($sHostname, $timeout = 50)
    Local $return_struc[4]
    ; [0] = Result (in ms)
    ; [1] = The hostname originally used
    ; [2] = Process handle (for internal use only)
    ; [3] = Buffer (for internal use only)
    
    $return_struc[1] = $sHostname
    $return_struc[2] = Run("ping " & $sHostname & " -n 1 -w " & $timeout, "", @SW_HIDE, $STDOUT_CHILD)
    
    Return $return_struc
EndFunc

Func _MSPingIsReady(ByRef $return_struc)
    Return ___MSPingReadOutput($return_struc)
EndFunc

Func _MSPingGetResult($return_struc)
    Return $return_struc[0]
EndFunc

Func _MSPingGetHostname($return_struc)
    Return $return_struc[1]
EndFunc

; Internal use only
Func ___MSPingReadOutput(ByRef $return_struc)
    $data = StdoutRead($return_struc[2])
    If (@error) Then
        ___MSPingParseResult($return_struc)
        Return 1
    Else
        $return_struc[3] &= $data
        Return 0
    EndIf
EndFunc

; Internal use only
Func ___MSPingParseResult(ByRef $return_struc)
    $result = StringRegExp($return_struc[3], "([0-9]*)ms", 3)
    If @error Then
        $return_struc[0] = -1
    Else
        $return_struc[0] = $result[0]
    EndIf
EndFunc

Func _IsPressed($sHexKey, $vDLL = 'user32.dll')
    ; $hexKey must be the value of one of the keys.
    ; _Is_Key_Pressed will return 0 if the key is not pressed, 1 if it is.
    Local $a_R = DllCall($vDLL, "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
    If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1
    Return 0
EndFunc   ;==>_IsPressed
Link to comment
Share on other sites

Here is a better GUI based off of llewxam's GUI posted in the thread previously.

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

AutoItSetOption("GUIOnEventMode", 1)

Global $MAX_PROCESS = 10 ; We spawn a maximum of 10 processes at once

$hDefault = GUICreate("")

$hGUI = GUICreate("Alive", 375, 300)
$hGo = GUICtrlCreateButton("Go", 230, 10, 57, 25)
$hInput = GUICtrlCreateInput("", 15, 10, 200)
$hAlive = GUICtrlCreateList("", 15, 64, 165, 200)
$hDead = GUICtrlCreateList("", 200, 64, 165, 200)
$hClear = GUICtrlCreateButton("Clear", 150, 275, 89, 25)
$hExample = GUICtrlCreateLabel("Ex. 192.168.1.* or 192.168.1-2.1-10", 15, 40)
$hAliveLabel = GUICtrlCreateLabel("Alive", 85, 255)
$hDeadLabel = GUICtrlCreateLabel("Dead", 275, 255)
$hProg = GUICtrlCreateProgress(200, 40, 165)
$hMaxProc = GUICtrlCreateInput($MAX_PROCESS, 335, 10, 30)
$hMaxProcLabel = GUICtrlCreateLabel("Max" & @CRLF & "Proc's", 295, 5, 30, 30)
GUICtrlSetOnEvent($hGo, "alive")
GUICtrlSetOnEvent($hClear, "clear")
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
GUICtrlSetState($hInput, $GUI_FOCUS)
GUISetState(@SW_SHOW)

While 1
    Sleep(50)
    If _IsPressed("0D") And WinActive($hGUI) Then alive()
WEnd

Func alive()
    GUICtrlSetState($hGo, $GUI_DISABLE)
    GUICtrlSetState($hClear, $GUI_DISABLE)
    
    $sAddress = GUICtrlRead($hInput)    
    If $sAddress = "" Then 
        error1("Input was null")
        Return
    EndIf
    
    $aArray = _GetIpAddressList($sAddress)
    If $aArray[0] = 0 Then 
        error1("Input was incorrect. Check syntax.")
        Return
    EndIf
    
    $MAX_PROCESS = GUICtrlRead($hMaxProc)
    If $MAX_PROCESS = 0 Then $MAX_PROCESS = 1
    
    Local $aProcess[$MAX_PROCESS] ; An array to keep a reference to spawned processes, in the next loop we fill it with value 0
    For $i = 0 to UBound($aProcess) - 1
        $aProcess[$i] = 0
    Next
    
    Local $i = 1
    Local $iFinished = 1
    While True
        For $n = 0 to UBound($aProcess) - 1
            If ($i <> UBound($aArray) AND $aProcess[$n] == 0) Then ; Check if we need a spot, and there is an existing spot
                    $aProcess[$n] = _MSPing($aArray[$i])
                    $i += 1
            Else
                If ($aProcess[$n] <> 0 And _MSPingIsReady($aProcess[$n])) Then
                    
                    GUICtrlSetData($hProg, ($iFinished / 255) * 100)
                    
                    $sHostname = _MSPingGetHostname($aProcess[$n])
                    $sResult = _MSPingGetResult($aProcess[$n])
                    If ($sResult <> -1) Then
                        GUICtrlSetData($hAlive, $sHostname & " is alive " & $sResult & " ms" & @CRLF)
                    Else
                        GUICtrlSetData($hDead, $sHostname & " is dead" & @CRLF)
                    EndIf

                    ; Free up an empty space for the next address to Ping
                    $aProcess[$n] = 0
                        
                    $iFinished += 1 ; <=== New line
                    If ($iFinished == UBound($aArray)) Then ExitLoop 2 ; Return
                EndIf
            EndIf
        Next
        Sleep(50) ; Give existing ping commands some time to process the request
    WEnd
    
    GUICtrlSetData($hProg, 0)
    enableButtons()
EndFunc

Func error1($sMessage)
    MsgBox(0, "Error", $sMessage, 0, $hDefault)
    Sleep(50)
    enableButtons()
    GUICtrlSetState($hInput, $GUI_FOCUS)
EndFunc

Func enableButtons()
    GUICtrlSetState($hGo, @SW_ENABLE)
    GUICtrlSetState($hClear, @SW_ENABLE)
EndFunc

Func clear()
    GUICtrlSetData($hAlive, "")
    GUICtrlSetData($hDead, "")
EndFunc

Func _GetIpAddressList($ipFormat)
    Local $aResult[1]
    $aResult[0] = 0
    
    If StringInStr(StringStripWS($ipFormat, 3), " ") Or StringInStr($ipFormat, ".", "", 4) Then Return $aResult
    
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")
    
    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i + 1], "-") Then
            If StringInStr($ipSplit[$i + 1], "-", "", 2) Then Return $aResult
            $m = StringSplit($ipSplit[$i +1 ],"-")
            For $i2 = 1 to $m[0] 
                If Number($m[$i2]) > 255 Or Number($m[$i2]) < 0 Then Return $aResult
                $ipRange[$i][$i2 - 1] = Number($m[$i2])
            Next
        Else
            $n = Number($ipSplit[$i + 1])
            If $n > 255 Or $n < 0 Then Return $aResult
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $aResult[$totalPermu + 1], $i = 1

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $aResult[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next
    
    $aResult[0] = $i - 1
    Return $aResult
EndFunc   ;==>_GetIpAddressList

Func _Exit()
    Exit
EndFunc

Func _MSPing($sHostname, $timeout = 50)
    Local $return_struc[4]
    ; [0] = Result (in ms)
    ; [1] = The hostname originally used
    ; [2] = Process handle (for internal use only)
    ; [3] = Buffer (for internal use only)
    
    $return_struc[1] = $sHostname
    $return_struc[2] = Run("ping " & $sHostname & " -n 1 -w " & $timeout, "", @SW_HIDE, $STDOUT_CHILD)
    
    Return $return_struc
EndFunc

Func _MSPingIsReady(ByRef $return_struc)
    Return ___MSPingReadOutput($return_struc)
EndFunc

Func _MSPingGetResult($return_struc)
    Return $return_struc[0]
EndFunc

Func _MSPingGetHostname($return_struc)
    Return $return_struc[1]
EndFunc

; Internal use only
Func ___MSPingReadOutput(ByRef $return_struc)
    $data = StdoutRead($return_struc[2])
    If (@error) Then
        ___MSPingParseResult($return_struc)
        Return 1
    Else
        $return_struc[3] &= $data
        Return 0
    EndIf
EndFunc

; Internal use only
Func ___MSPingParseResult(ByRef $return_struc)
    $result = StringRegExp($return_struc[3], "([0-9]*)ms", 3)
    If @error Then
        $return_struc[0] = -1
    Else
        $return_struc[0] = $result[0]
    EndIf
EndFunc

Func _IsPressed($sHexKey, $vDLL = 'user32.dll')
    ; $hexKey must be the value of one of the keys.
    ; _Is_Key_Pressed will return 0 if the key is not pressed, 1 if it is.
    Local $a_R = DllCall($vDLL, "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
    If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1
    Return 0
EndFunc   ;==>_IsPressed
Link to comment
Share on other sites

Here is a better GUI based off of llewxam's GUI posted in the thread previously.

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

AutoItSetOption("GUIOnEventMode", 1)

Global $MAX_PROCESS = 10 ; We spawn a maximum of 10 processes at once

$hDefault = GUICreate("")

$hGUI = GUICreate("Alive", 375, 300)
$hGo = GUICtrlCreateButton("Go", 230, 10, 57, 25)
$hInput = GUICtrlCreateInput("", 15, 10, 200)
$hAlive = GUICtrlCreateList("", 15, 64, 165, 200)
$hDead = GUICtrlCreateList("", 200, 64, 165, 200)
$hClear = GUICtrlCreateButton("Clear", 150, 275, 89, 25)
$hExample = GUICtrlCreateLabel("Ex. 192.168.1.* or 192.168.1-2.1-10", 15, 40)
$hAliveLabel = GUICtrlCreateLabel("Alive", 85, 255)
$hDeadLabel = GUICtrlCreateLabel("Dead", 275, 255)
$hProg = GUICtrlCreateProgress(200, 40, 165)
$hMaxProc = GUICtrlCreateInput($MAX_PROCESS, 335, 10, 30)
$hMaxProcLabel = GUICtrlCreateLabel("Max" & @CRLF & "Proc's", 295, 5, 30, 30)
GUICtrlSetOnEvent($hGo, "alive")
GUICtrlSetOnEvent($hClear, "clear")
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
GUICtrlSetState($hInput, $GUI_FOCUS)
GUISetState(@SW_SHOW)

While 1
    Sleep(50)
    If _IsPressed("0D") And WinActive($hGUI) Then alive()
WEnd

Func alive()
    GUICtrlSetState($hGo, $GUI_DISABLE)
    GUICtrlSetState($hClear, $GUI_DISABLE)
    
    $sAddress = GUICtrlRead($hInput)    
    If $sAddress = "" Then 
        error1("Input was null")
        Return
    EndIf
    
    $aArray = _GetIpAddressList($sAddress)
    If $aArray[0] = 0 Then 
        error1("Input was incorrect. Check syntax.")
        Return
    EndIf
    
    $MAX_PROCESS = GUICtrlRead($hMaxProc)
    If $MAX_PROCESS = 0 Then $MAX_PROCESS = 1
    
    Local $aProcess[$MAX_PROCESS] ; An array to keep a reference to spawned processes, in the next loop we fill it with value 0
    For $i = 0 to UBound($aProcess) - 1
        $aProcess[$i] = 0
    Next
    
    Local $i = 1
    Local $iFinished = 1
    While True
        For $n = 0 to UBound($aProcess) - 1
            If ($i <> UBound($aArray) AND $aProcess[$n] == 0) Then ; Check if we need a spot, and there is an existing spot
                    $aProcess[$n] = _MSPing($aArray[$i])
                    $i += 1
            Else
                If ($aProcess[$n] <> 0 And _MSPingIsReady($aProcess[$n])) Then
                    
                    GUICtrlSetData($hProg, ($iFinished / 255) * 100)
                    
                    $sHostname = _MSPingGetHostname($aProcess[$n])
                    $sResult = _MSPingGetResult($aProcess[$n])
                    If ($sResult <> -1) Then
                        GUICtrlSetData($hAlive, $sHostname & " is alive " & $sResult & " ms" & @CRLF)
                    Else
                        GUICtrlSetData($hDead, $sHostname & " is dead" & @CRLF)
                    EndIf

                    ; Free up an empty space for the next address to Ping
                    $aProcess[$n] = 0
                        
                    $iFinished += 1 ; <=== New line
                    If ($iFinished == UBound($aArray)) Then ExitLoop 2 ; Return
                EndIf
            EndIf
        Next
        Sleep(50) ; Give existing ping commands some time to process the request
    WEnd
    
    GUICtrlSetData($hProg, 0)
    enableButtons()
EndFunc

Func error1($sMessage)
    MsgBox(0, "Error", $sMessage, 0, $hDefault)
    Sleep(50)
    enableButtons()
    GUICtrlSetState($hInput, $GUI_FOCUS)
EndFunc

Func enableButtons()
    GUICtrlSetState($hGo, @SW_ENABLE)
    GUICtrlSetState($hClear, @SW_ENABLE)
EndFunc

Func clear()
    GUICtrlSetData($hAlive, "")
    GUICtrlSetData($hDead, "")
EndFunc

Func _GetIpAddressList($ipFormat)
    Local $aResult[1]
    $aResult[0] = 0
    
    If StringInStr(StringStripWS($ipFormat, 3), " ") Or StringInStr($ipFormat, ".", "", 4) Then Return $aResult
    
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")
    
    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i + 1], "-") Then
            If StringInStr($ipSplit[$i + 1], "-", "", 2) Then Return $aResult
            $m = StringSplit($ipSplit[$i +1 ],"-")
            For $i2 = 1 to $m[0] 
                If Number($m[$i2]) > 255 Or Number($m[$i2]) < 0 Then Return $aResult
                $ipRange[$i][$i2 - 1] = Number($m[$i2])
            Next
        Else
            $n = Number($ipSplit[$i + 1])
            If $n > 255 Or $n < 0 Then Return $aResult
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $aResult[$totalPermu + 1], $i = 1

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $aResult[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next
    
    $aResult[0] = $i - 1
    Return $aResult
EndFunc   ;==>_GetIpAddressList

Func _Exit()
    Exit
EndFunc

Func _MSPing($sHostname, $timeout = 50)
    Local $return_struc[4]
    ; [0] = Result (in ms)
    ; [1] = The hostname originally used
    ; [2] = Process handle (for internal use only)
    ; [3] = Buffer (for internal use only)
    
    $return_struc[1] = $sHostname
    $return_struc[2] = Run("ping " & $sHostname & " -n 1 -w " & $timeout, "", @SW_HIDE, $STDOUT_CHILD)
    
    Return $return_struc
EndFunc

Func _MSPingIsReady(ByRef $return_struc)
    Return ___MSPingReadOutput($return_struc)
EndFunc

Func _MSPingGetResult($return_struc)
    Return $return_struc[0]
EndFunc

Func _MSPingGetHostname($return_struc)
    Return $return_struc[1]
EndFunc

; Internal use only
Func ___MSPingReadOutput(ByRef $return_struc)
    $data = StdoutRead($return_struc[2])
    If (@error) Then
        ___MSPingParseResult($return_struc)
        Return 1
    Else
        $return_struc[3] &= $data
        Return 0
    EndIf
EndFunc

; Internal use only
Func ___MSPingParseResult(ByRef $return_struc)
    $result = StringRegExp($return_struc[3], "([0-9]*)ms", 3)
    If @error Then
        $return_struc[0] = -1
    Else
        $return_struc[0] = $result[0]
    EndIf
EndFunc

Func _IsPressed($sHexKey, $vDLL = 'user32.dll')
    ; $hexKey must be the value of one of the keys.
    ; _Is_Key_Pressed will return 0 if the key is not pressed, 1 if it is.
    Local $a_R = DllCall($vDLL, "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
    If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1
    Return 0
EndFunc   ;==>_IsPressed

Exemplary work! Well done. This is a great collaboration. I'm definitely using this GUI as a stand alone application in the future.

Edit: I see you changed the behavior of the code to return a [0] element indicating how large the array is. That is not a wise choice and I don't like it at all.

Edited by Manadar
Link to comment
Share on other sites

Edit: I see you changed the behavior of the code to return a [0] element indicating how large the array is. That is not a wise choice and I don't like it at all.

Explain! What makes this so terrible? Edited by SoulA
Link to comment
Share on other sites

http://www.autoitscript.com/forum/index.php?showtopic=16321

http://www.autoitscript.com/forum/index.php?showtopic=60997

I see. Good info thank you. Here is updated code to adhere. Also changed the progress bar to be more accurate and did a few GUI tweaks so it looked a tad nicer. Only thing I can think of to add is to be able to copy elements out of the list but I'm drawing a blank on how to do that. If someone else can come up with a good way please feel free to add on!

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

AutoItSetOption("GUIOnEventMode", 1)

Global $MAX_PROCESS = 10 ; We spawn a maximum of 10 processes at once

$hGUI = GUICreate("Alive", 365, 320, -1, -1, $WS_SYSMENU)
$hGo = GUICtrlCreateButton("Go", 210, 10, 57, 25)
$hInput = GUICtrlCreateInput("", 5, 10, 200)
$hAlive = GUICtrlCreateList("", 5, 64, 170, 200, -1, 0x00000100)
$hDead = GUICtrlCreateList("", 185, 64, 170, 200, -1, 0x00000100)
$hClear = GUICtrlCreateButton("Clear", 135, 265, 89, 25)
$hExample = GUICtrlCreateLabel("Ex. 192.168.1.* or 192.168.1-2.1-10", 5, 40)
$hAliveLabel = GUICtrlCreateLabel("Alive", 75, 265)
$hDeadLabel = GUICtrlCreateLabel("Dead", 265, 265)
$hProg = GUICtrlCreateProgress(190, 40, 165)
$hMaxProc = GUICtrlCreateInput($MAX_PROCESS, 325, 10, 30)
$hMaxProcLabel = GUICtrlCreateLabel("Max" & @CRLF & "Proc's", 285, 5, 30, 30)
GUICtrlSetOnEvent($hGo, "alive")
GUICtrlSetOnEvent($hClear, "clear")
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
GUICtrlSetState($hInput, $GUI_FOCUS)
GUISetState(@SW_SHOW)

While 1
    Sleep(50)
    If _IsPressed("0D") And WinActive($hGUI) Then alive()
WEnd

Func alive()
    GUICtrlSetState($hGo, $GUI_DISABLE)
    GUICtrlSetState($hClear, $GUI_DISABLE)
    
    $sAddress = GUICtrlRead($hInput)    
    If $sAddress = "" Then 
        error1("Input was null")
        Return
    EndIf
    
    $aArray = _GetIpAddressList($sAddress)
    If $aArray[0] = "" Then 
        error1("Input was incorrect. Check syntax.")
        Return
    EndIf
    
    $MAX_PROCESS = GUICtrlRead($hMaxProc)
    If $MAX_PROCESS = 0 Then $MAX_PROCESS = 1
    
    Local $aProcess[$MAX_PROCESS] ; An array to keep a reference to spawned processes, in the next loop we fill it with value 0
    For $i = 0 to UBound($aProcess) - 1
        $aProcess[$i] = 0
    Next
    
    Local $i = 0
    Local $iFinished = 0
    While True
        For $n = 0 to UBound($aProcess) - 1
            If ($i <> UBound($aArray) AND $aProcess[$n] == 0) Then ; Check if we need a spot, and there is an existing spot
                    $aProcess[$n] = _MSPing($aArray[$i])
                    $i += 1
            Else
                If ($aProcess[$n] <> 0 And _MSPingIsReady($aProcess[$n])) Then
                    
                    GUICtrlSetData($hProg, ($iFinished / (UBound($aArray) - 1)) * 100)
                    
                    $sHostname = _MSPingGetHostname($aProcess[$n])
                    $sResult = _MSPingGetResult($aProcess[$n])
                    If ($sResult <> -1) Then
                        GUICtrlSetData($hAlive, $sHostname & " is alive " & $sResult & " ms" & @CRLF)
                    Else
                        GUICtrlSetData($hDead, $sHostname & " is dead" & @CRLF)
                    EndIf

                    ; Free up an empty space for the next address to Ping
                    $aProcess[$n] = 0
                        
                    $iFinished += 1 ; <=== New line
                    If $iFinished == UBound($aArray) Then ExitLoop 2 ; Return
                EndIf
            EndIf
        Next
        Sleep(50) ; Give existing ping commands some time to process the request
    WEnd
    
    GUICtrlSetData($hProg, 0)
    enableButtons()
EndFunc

Func error1($sMessage)
    MsgBox(0, "Error", $sMessage, 0, $hGUI)
    Sleep(50)
    enableButtons()
    GUICtrlSetState($hInput, $GUI_FOCUS)
EndFunc

Func enableButtons()
    GUICtrlSetState($hGo, @SW_ENABLE)
    GUICtrlSetState($hClear, @SW_ENABLE)
EndFunc

Func clear()
    GUICtrlSetData($hAlive, "")
    GUICtrlSetData($hDead, "")
EndFunc

Func _GetIpAddressList($ipFormat)
    Local $aResult[1]
    
    If StringInStr(StringStripWS($ipFormat, 3), " ") Or StringInStr($ipFormat, ".", "", 4) Then Return $aResult
    
    $ipFormat = StringReplace($ipFormat, "*", "1-255")
    $ipSplit = StringSplit($ipFormat, ".")
    
    If $ipSplit[0] <> 4 Then Return $aResult
    
    Local $ipRange[4][2], $totalPermu = 1

    For $i = 0 To 3
        If StringInStr($ipSplit[$i + 1], "-") Then
            If StringInStr($ipSplit[$i + 1], "-", "", 2) Then Return $aResult
            $m = StringSplit($ipSplit[$i +1 ],"-")
            For $i2 = 1 to $m[0] 
                If Number($m[$i2]) > 255 Or Number($m[$i2]) < 0 Then Return $aResult
                $ipRange[$i][$i2 - 1] = Number($m[$i2])
            Next
        Else
            $n = Number($ipSplit[$i + 1])
            If $n > 255 Or $n < 0 Then Return $aResult
            $ipRange[$i][0] = $n
            $ipRange[$i][1] = $n
        EndIf

        $totalPermu *= $ipRange[$i][1] - $ipRange[$i][0] + 1
    Next

    Local $aResult[$totalPermu], $i = 0

    For $a = $ipRange[0][0] To $ipRange[0][1]
        For $b = $ipRange[1][0] To $ipRange[1][1]
            For $c = $ipRange[2][0] To $ipRange[2][1]
                For $d = $ipRange[3][0] To $ipRange[3][1]
                    $aResult[$i] = $a & "." & $b & "." & $c & "." & $d
                    $i += 1
                Next
            Next
        Next
    Next
    
    Return $aResult
EndFunc   ;==>_GetIpAddressList

Func _Exit()
    Exit
EndFunc

Func _MSPing($sHostname, $timeout = 50)
    Local $return_struc[4]
    ; [0] = Result (in ms)
    ; [1] = The hostname originally used
    ; [2] = Process handle (for internal use only)
    ; [3] = Buffer (for internal use only)
    
    $return_struc[1] = $sHostname
    $return_struc[2] = Run("ping " & $sHostname & " -n 1 -w " & $timeout, "", @SW_HIDE, $STDOUT_CHILD)
    
    Return $return_struc
EndFunc

Func _MSPingIsReady(ByRef $return_struc)
    Return ___MSPingReadOutput($return_struc)
EndFunc

Func _MSPingGetResult($return_struc)
    Return $return_struc[0]
EndFunc

Func _MSPingGetHostname($return_struc)
    Return $return_struc[1]
EndFunc

; Internal use only
Func ___MSPingReadOutput(ByRef $return_struc)
    $data = StdoutRead($return_struc[2])
    If (@error) Then
        ___MSPingParseResult($return_struc)
        Return 1
    Else
        $return_struc[3] &= $data
        Return 0
    EndIf
EndFunc

; Internal use only
Func ___MSPingParseResult(ByRef $return_struc)
    $result = StringRegExp($return_struc[3], "([0-9]*)ms", 3)
    If @error Then
        $return_struc[0] = -1
    Else
        $return_struc[0] = $result[0]
    EndIf
EndFunc

Func _IsPressed($sHexKey, $vDLL = 'user32.dll')
    ; $hexKey must be the value of one of the keys.
    ; _Is_Key_Pressed will return 0 if the key is not pressed, 1 if it is.
    Local $a_R = DllCall($vDLL, "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
    If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1
    Return 0
EndFunc   ;==>_IsPressed
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...