Jump to content

Simple question about For In Next loop


jstump1
 Share

Recommended Posts

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

...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]

Link to comment
Share on other sites

...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

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...