Jump to content
Sign in to follow this  
jstump1

Simple question about For In Next loop

Recommended Posts

jstump1

Hello - I am trying to create an automated way of creating Wake-On-Lan packets for my network. I want to turn all the computers on at a certain time. I have to do more testing but my initial script appears to work. I get an error message though from the AutoIT3.EXE. Maybe you can tell me what I've done wrong.

Error Message:

>"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "U:\scripts\SendWOL.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams

+>23:01:32 Starting AutoIt3Wrapper v.1.10.1.14 Environment(Language:0409 Keyboard:00000409 OS:WIN_XP/Service Pack 2 CPU:X86 ANSI)

>Running AU3Check (1.54.13.0) from:C:\Program Files\AutoIt3

+>23:01:34 AU3Check ended.rc:0

>Running:(3.2.12.1):C:\Program Files\AutoIt3\autoit3a.exe "U:\scripts\SendWOL.au3"

U:\scripts\SendWOL.au3 (87) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

$ComputerFileHandle = FileOpen ($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast] & "\" & $ComputerList[$CurrentFile], 0)

$ComputerFileHandle = FileOpen ($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast] & "\" & ^ ERROR->23:01:52 AutoIT3.exe ended.rc:1

+>23:01:53 AutoIt3Wrapper Finished

>Exit code: 1 Time: 22.377

#Region AutoIt3Wrapper directives section
#AutoIt3Wrapper_Prompt=y
#AutoIt3Wrapper_Run_Debug_Mode=n
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Allow_Decompile=n
#AutoIt3Wrapper_UseAnsi=y
#AutoIt3Wrapper_Res_Comment=send wake on lan packet to a mac address
#AutoIt3Wrapper_Res_Description=wake on lan packet generator
#AutoIt3Wrapper_Res_Fileversion=1.0.0.33
#AutoIt3Wrapper_Res_FileVersion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=CopyLeft 2009 - James Stump
#AutoIt3Wrapper_Res_Field=Licence|GNU GPL V2 (http://www.gnu.org/copyleft/gpl.html)
#EndRegion

;#NoTrayIcon

#include <String.au3>
#Include <File.au3>
#Include <Array.au3>

Opt("MustDeclareVars", 0)
;Opt("RunErrorsFatal", 0)

Const $wbemFlagReturnImmediately = 0x10
Const $wbemFlagForwardOnly = 0x20
Global $macAddr, $broadcast_str, $ComputerName, $DataDir, $ComputerFileHandle, $LogFile

; sends a wake-on-lan packet on the broadcast address
Func wol($macAddr, $broadcastAddr)
    UDPStartup()
    Local $conn = UDPOpen($broadcastAddr, 7)
    Local $packet = _HexToString("FFFFFFFFFFFF" & _StringRepeat(StringUpper($macAddr), 16))
    UDPSend($conn, $packet)
    If @error Then
        SetError(@error)
        Return False
    EndIf
    UDPCloseSocket($conn)
    UDPShutdown()
    Return True
EndFunc   ;==>wol

; Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address
Func ip2long($ip_str)
    Local $ip_arr = StringRegExp($ip_str, "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})", 1)
    If @error Then
        SetError(1) ; incorrect address
        Return 0
    EndIf
    Return BitOR( _
            BitShift($ip_arr[0], -24), _
            BitShift($ip_arr[1], -16), _
            BitShift($ip_arr[2], -8), _
            $ip_arr[3])
EndFunc   ;==>ip2long

; send wake on lan packet on each ip enabled local interface
Func SendWOLPacket()
Local $objWMIService = ObjGet("winmgmts:\\.\root\CIMV2")
Local $colItems = $objWMIService.ExecQuery ("SELECT IPAddress, IPSubnet FROM Win32_NetworkAdapterConfiguration " & _
        "WHERE IPEnabled<>0", "WQL", BitOR($wbemFlagReturnImmediately, $wbemFlagForwardOnly))
$LogFile = FileOpen( IniRead ( @ScriptDir & "\SendWOL.ini", "Files", "LogFiles", @ScriptDir) & "\" & @MON & @MDAY & @YEAR & "SendLog.csv", 1)
If IsObj($colItems) Then
    For $objItems In $colItems
        With $objItems
            Local $ip = ip2long(.IPAddress (0))
            If $ip <> 0 Then
                If wol($macAddr, $broadcast_str) Then
                    FileWriteLine($LogFile, $ComputerName & "," & "TRUE," & "," & $macAddr & "," & $broadcast_str)
                Else
                    FileWriteLine($LogFile, $ComputerName & "," & "FALSE," & "," & $macAddr & "," & $broadcast_str) 
                EndIf
            EndIf
        EndWith
    Next
EndIf
FileClose ($LogFile)
EndFunc    ;==>SendWOLPacket

$DataDir = IniRead ( @ScriptDir & "\SendWOL.ini", "Files", "BroadCastAddr", @ScriptDir)
$BroadcastAddrList = _FileListToArray($DataDir, "*.*", 2)
For $CurrentBroadcast In $BroadcastAddrList
    $ComputerList=_FileListToArray($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast], "*.csv", 1)
    For $CurrentFile In $ComputerList
        $ComputerFileHandle = FileOpen ($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast] & "\" & $ComputerList[$CurrentFile], 0)
        While 1
            $Contents = FileReadLine ($ComputerFileHandle)
            If @error = 1 Then
                    FileClose ($ComputerFileHandle)
                    ExitLoop
                Else
            EndIf
            $ContentsArray = StringSplit($Contents, ',')
            If $ContentsArray[0] <= 1 Then
                    FileClose ($ComputerFileHandle)
                    ExitLoop
                Else
            EndIf
            $macAddr = $ContentsArray[1]
            $broadcast_str = $ContentsArray[2]
            $ComputerName = $ComputerList[$CurrentFile]
            SendWolPacket()
        WEnd
    Next
Next
Exit

Thanks,

Stumppc

Share this post


Link to post
Share on other sites
Andreik

Check is $ComputerList is an array, and then if is array, check if in $ComputerList are ehoungh subscripts. If $CurrentFile is higher than $ComputerList subscripts number you will got this kind of error.

Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites
jstump1

Thank you Andreik -

You got me thinking...I changed my loops to this:

For $CurrentBroadcast = 1 To UBound($BroadcastAddrList, 1) - 1
For $CurrentFile = 1 To UBound($ComputerList, 1) - 1

It works like a charm now. I had used _FileListToArray() and it doesn't give me data I want to use out of the first item in the array anyway.

I guess another way to do it woule be:

For $CurrentBroadcast = 1 To $BroadcastAddrList[0]
For $CurrentFile = 1 To $ComputerList[0]

~Stumppc

Share this post


Link to post
Share on other sites
herewasplato

...but to answer your original question.

Look at this loop...

$array = StringSplit("012345", "")
For $element In $array
    ConsoleWrite($element & @CR)
Next
...and then look at your original code again.

Lines like this:

$ComputerList=_FileListToArray($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast], "*.csv", 1)


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites
jstump1

...but to answer your original question.

Look at this loop...

$array = StringSplit("012345", "")
For $element In $array
    ConsoleWrite($element & @CR)
Next
...and then look at your original code again.

Lines like this:

$ComputerList=_FileListToArray($DataDir & "\" & $BroadcastAddrList[$CurrentBroadcast], "*.csv", 1)

OK I understand now. The first time the variable $element is populated with data it is the integer of how many pieces of data are contained in the object or array. Just like how the _FileListToArray() function works. That made my subscripts call 1 too high at last iteration of the loop. Wish that was in the documentation...I'm not a programmer by trade, just a scripter by necessity;)

Thanks - case closed I guess. At least now I know my original choice for a looping function could have worked if I had understood how that stepping variable operated.

Thanks

Stumppc

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  

×