Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Is there a way to "restart" a FOR loop?

Status
Not open for further replies.

keybrdcowboy

IS-IT--Management
Aug 31, 2004
96
US
Hopefully someone can help me. I need a way to "restart" a for loop. I have a loop that processes each entry in an array, and does stuff to each account in the array. However, some of the accounts are not real accounts, and I get an error. I am trying to find a way to test for the error, and if there is one, then have it just skip that account and move on to the next one. I already have the testing for an error part down, but how can I get it to just skip that account and then go to the next one in the account? I have found the Exit For command, but that cancels the whole loop, and then nobody processes. Can anyone provide some help? Thanks.
 
Well, in a situation like that I would typically just wrap all of the code that you want to only execute for real accounts in an If - Then - End If block.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Alright, I don't understand what you are trying to say. I currently have a program... the first thing it does is read in a textfile which contains all the usernames I am trying to manipulate. (Currently around 730 users) The first thing the script does is take each username, connect to AD, grab the SID for that username, then turn around and connect to Exchange using that SID. After it makes the connection to Exchange, it pulls certain fields from Exchange and puts those in variables. It then connects back to that user account in AD, and inputs those variables into fields in the user account in AD. My problem is when it goes to conenct to Exchange and can't find the user (usually because the account is actually a service account or student account or something). I would like for it to end there and just go on to the next record in the array. How can I make it do that? I can exit the For loop all together, but then it won't continue to process the rest of the usernames. Is there anyway to just restart the loop, or tell it to skip the record it's on and go on to the next one? Thanks. Let me know if you want me to post my code...
 
This is mostly pseudo code, but it should illustrate the concept:

Code:
For Loop to process all users
  Use the current user name to connect to AD
  Get the SID for that username
  On Error Resume Next
  Connect to Exchange using the SID
  If Err.Number = 0 Then
    On Error Goto 0
    Pull fields from exchange and put them into variables
    Connect back to the user account in AD
    Input variables into AD fields
  End If
  On Error Goto 0
Next

This way, it only continues processing a username if the connection to Exchange does not error out.

If you post your actual code, we can give better feedback as well.


[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
You can always reset the value that is being counted in the for loop (for x = 1 to 100, reset x to 0 at some point), or you could use the good old GoTo statement to send execution to a line above the for loop.
 
I don't think that is really what he wnats to do. I think what he really wants to do is to immediately execute the next iteration of the loop if some condition exists.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Plus, it is just my opinion, but in my opinion both resetting the iteration variable and using Goto statements are code maintenance nightmare creators.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Thanks TomThumb. I can see what your saying, the only thing is that I need that error checking in 3 or 4 different parts of my For loop. But I can probably still work with that. Here's my actual code, case anyone wants to check it out.

Code:
Option Explicit

Dim oConn 
Dim oRS 
Dim oSid
Dim strServerName, strGALEmail, strGALLastName, strGALFirstName, strGALDisplayName, strGALDescription, strGALCountry, strGALCity, strGALOffice
Dim strDomain, strGALZip, strGALState, strGALStreet, strGALTelNum, strGALTitle, strGALRank, oFSO, readFile, outFile, iUpperBound
Dim strUserName, oRootDSE, oConnection, oCommand, oRecordSet, strConnect, UserObj, strAD
Dim strSid
Dim strQuery
Public strUser

Const ADS_SID_HEXSTRING = 1
Const ADS_SID_WINNT_PATH = 5

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set readFile = oFSO.OpenTextFile("C:\documents and settings\desktop\users.txt")
Set outFile = oFSO.CreateTextFile("C:\documents and settings\desktop\UpdateADInfo.log", True)
Set oSid = CreateObject("ADsSid")
Set oConn = CreateObject("ADODB.Connection") 'Create an ADO Connection
oConn.Provider = "ADsDSOOBJECT"              ' ADSI OLE-DB provider
oConn.Open "ADs Provider"


' Opens a textfile containg the usernames you want to pull from exchange and puts them in an array
iUpperBound = 0
While Not readFile.AtEndOfStream
  ReDim Preserve arrUserNames(iUpperBound)
  arrUserNames(UBound(arrUserNames)) = readFile.ReadLine
  iUpperBound = iUpperBound + 1
Wend
readFile.Close

' Code that conects to the user's GAL info and puts it into variables
For Each strUser in arrUserNames
  strUserName = strUser
  On Error Resume Next
  oSid.SetAs ADS_SID_WINNT_PATH, "WinNT://domain/" & strUser  'Get the user account SID 
  strSid = oSid.GetAs(ADS_SID_HEXSTRING)
  
  If Err <> 0 Then
    outFile.WriteLine "Could not find " & strUser & " in AD." & "     " & Date & "     " & Time
  End If
  On Error Goto 0
  strQuery = "<LDAP://server>;(&(objectClass=person)(Assoc-NT-Account=" & strSid & "));" & _
           "adspath,mail,sn,givenName,cn,description,co,l,physicalDeliveryOfficeName,postalCode,st,postaladdress,TelephoneNumber,title," & _
           "Extension-Attribute-1;subtree"
  Set oRS = oConn.Execute(strQuery)
  If oRS.EOF And oRS.EOF Then
    outFile.Writeline "Could not locate user " & strUser & "'s information in the GAL." & "       " & Date & "     " & Time
  Else
    strGALEmail = oRS.Fields("mail")
    strGALLastName = oRS.Fields("sn")
    strGALFirstName = oRS.Fields("givenName")
    strGALDisplayName = oRS.Fields("cn")
    strGALDescription = oRS.Fields("description")
    strGALCountry = oRS.Fields("co")
    strGALCity = oRS.Fields("l")
    strGALOffice = oRS.Fields("physicalDeliveryOfficeName")
    strGALZip = oRS.Fields("postalCode")
    strGALState = oRS.Fields("st")
    strGALStreet = oRS.Fields("postaladdress")
    strGALTelNum = oRS.Fields("TelephoneNumber")
    strGALTitle = oRS.Fields("title")
    strGALRank = oRS.Fields("Extension-Attribute-1")
  End If

' This line uses the username from above, connects to it in AD, and returns the full Distinguished Name
strConnect = fncConnectAD(strUserName)

' The following code connects to the user's account in AD and updates the account info with the info from the GAL
On Error Resume Next
Set UserObj = GetObject("LDAP://" & strConnect)
'On Error Goto 0
If Err <> 0 Then
   outFile.Writeline "There was an error connecting to " & strUserName & "'s account in Active Directory." & "     " & Date & "     " & Time
   Err.Clear
Else
   UserObj.Put ("mail"), (strGALEmail)
   UserObj.Put ("sn"), (strGALLastName)
   UserObj.Put ("givenName"), (strGALFirstName)
   UserObj.Put ("displayName"), (strGALDisplayName)
   UserObj.Put ("description"), (strGALDisplayName)
   'UserObj.Put ("description"), (strGALDescription)
   UserObj.Put ("co"), (strGALCountry)
   UserObj.Put ("l"), (strGALCity)
   UserObj.Put ("physicalDeliveryOfficeName"), (strGALOffice)
   UserObj.Put ("postalCode"), (strGALZip)
   UserObj.Put ("st"), (strGALState)
   UserObj.Put ("streetAddress"), (strGALStreet)
   UserObj.Put ("telephoneNumber"), (strGALTelNum)
   UserObj.Put ("title"), (strGALTitle)
   UserObj.SetInfo
End If
On Error Goto 0
Next

wscript.echo "Done"


' This funtion will take a username and return the complete Distinguished Name
Public Function fncConnectAD(strUsername)
	Set oRootDSE = GetObject("LDAP://rootDSE")
	Set oConnection = CreateObject("ADODB.Connection")
	oConnection.Open "Provider=ADsDSOObject;"
	Set oCommand = CreateObject("ADODB.Command")
	oCommand.ActiveConnection = oConnection
	oCommand.CommandText = "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;(&(objectCategory=User)(samAccountName=" & _
     	     strUserName & "));distinguishedName;subtree"
	Set oRecordSet = oCommand.Execute
	On Error Resume Next
        fncConnectAD = oRecordSet.Fields("distinguishedName")
        On Error Goto 0
End Function

 
I'm generally not an advocate of having large blocks of code being covered by On error Resume next, however in a situation like this where there are several point that an error could be thrown that you want to ignore, it can be useful. If you want to go that route, I would put an On Error Resume next right before you start doing your AD and Exchange queries. Then be sure that you do an Err.Clear before each subsequent statement that you expect to periodically fail and check the value of Err.Number immediately after the statement that you expect to fail.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
Well, the problem I'm having is that the account doesn't exist in Exchange, but it does in Active Directory. So it ignores the error on the GAL part, but then it goes to try and complete the AD part. I would like for the FOR loop to just move to the next record when it fails on teh GAL part.... I think I can use your earlier example to accopmlish that..... so there's no method or anything to restart the FOR loop? Thought there would be something like that....
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top