Sign in to follow this  
Followers 0
jvanegmond

Generate ip addresses based on format

15 posts in this topic

#1 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites



Share this post


Link to post
Share on other sites

Very nice.

Share this post


Link to post
Share on other sites

Just out of curiosity, what drove you to need such a func? I'd add some error checking as well (my two cents).

This thread did. I can combine these scripts to make a pretty awesome network prober.

Share this post


Link to post
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.)

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

Very nice function. I definitely will use this.


[left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left]

Share this post


Link to post
Share on other sites

This function should be an official UDF once it gets error checking. Anyway you can throw that in there? You have come this far.

Share this post


Link to post
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

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

Explain! What makes this so terrible?

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

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

Share this post


Link to post
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

Share this post


Link to post
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
Sign in to follow this  
Followers 0