Adding/Editing Active Directory attributes

I work for a school district and we're becoming a "Google District".  We're giving our students gmail accounts but for Google to be able to import and synchronize data, the email attribute needs to be present in AD on the student accounts.
I found a power shell script/command that seems to work fine but then bombs out.  I've resubmitted the script and it bombs every time, I don't know if the script is starting over from the beginning or picking up from where it bombed (I'm thinking it's starting over from the beginning).  
Both the script/command and the error are included in the attached PDF file.

If someone has a resolve for the error - fantastic!!.  Otherwise, about 2/3 of the student accounts have had the email (mail) attribute added so I could finish out if I could get a new script with a "where" clause added (where mail=blank or where not mail --- something to that effect)

Thanks in advance
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jeremy WeisingerSenior Network Consultant / EngineerCommented:
How many objects are you pulling?

It could be that the computer is running out of memory. You can try a few things.

1. Only pull the properties you need by adding the -Properties param:
-Properites distinguishedname,samaccountname,mail

Open in new window

2. Change the page size to something smaller like 50 (default is 250)
-ResultPageSize 50

Open in new window

So the new script would look like this:
Get-ADUser -LDAPFilter "(!(mail=\.name*))" -resultSetSize $null -ResultPageSize 50 -Properties distinguishedname,samaccountname,mail -searchbase "ou=test,dc=nwtraders,dc=com"| % {set-aduser -identity $_.distinguishedname -email ($_.samaccountname + "")}

Open in new window

skbarnardAuthor Commented:
I'm trying your modified script right now.  You're probably right about the computer running out of memory but this particular OU has around 33,000 objects.
Since more than half of the objects now have the email attribute, is there a way to have it search for those objects within that OU that don't have that attribute?  And if that attribute isn't present, then concatenate the samaccountname with the
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Sorry, meant to address that. The answer is the script is already only pulling users that don't have the email defined. If you kept running the current script over and over I imagine it would make it through all the users eventually.
Get Blueprints for Increased Customer Retention

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

skbarnardAuthor Commented:
So far, the script you provided hasn't bombed - not sure whether it's actually filling in the blanks yet either.
Will report back once this script completes (or bombs - hopefully the former :-) )
skbarnardAuthor Commented:
OK, as soon as I finished posting my previous response I checked the script and it has bombed with the same error::
Get-ADUser : The server has returned the following error: invalid enumeration context.
Is there a way to create a log as it iterates through the objects?  
Maybe it's encountering a bad account that is causing it to bomb but since no log is created, I have no way to check that.
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
After a little digging, the error is actually related to the length of time the query is running. So the best advice I can give you is to run the script from a DC that is powerful and isn't doing much and make sure it's querying itself and not another DC.

So change the -Server parameters to the DC you're using.
Get-ADUser -LDAPFilter "(!(mail=\.name*))" -resultSetSize $null -Server -Properties distinguishedname,samaccountname,mail -searchbase "ou=test,dc=nwtraders,dc=com"| % {set-aduser -identity $_.distinguishedname -email ($_.samaccountname + "") -Server}

Open in new window

skbarnardAuthor Commented:
I logged into a DC that is a pretty beefy server and right now, none of our DC's should be very busy since schools are out for Christmas break.  I'm currently running the script.
Right now, I can't see that the process is filling in the mail attribute but when I refresh the Active Directory Users and Computers screen, it appears possibly more have filled in.  
When I ran the process to start with, I didn't have the syntax quite right and it filled in the mail attribute with (exactly) "".  The process appears to overwrite this, but if it doesn't - is there a way to "find and replace" for that attribute?
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Yes, we can change the filter so that it pulls all the accounts that have "" as their email address.
Change the -LDAPFilter "(!(mail=\.name*)) to -Filter {mail -eq ""} and it will modify those accounts.

But the current filter is looking for the username in the email address so it should modify any accounts that don't have the proper email address configured.
skbarnardAuthor Commented:
That's pretty much what I thought but thanks for the filter change.
The script is still running - which is a good thing.  I'm hoping this time it will go to completion.
I'll post the results.
Have you considered using either PowerShell or tools like admod ( ) to perform the updates? This should allow you to store attribute value in a text file - manipulate its content - and save it back in AD

Moreover if consider for scripts its like With Powershell you could do this step by step on the Powershell command line and as you successfully complete each step you can build your script.
You will need to ensure you have a 2008 DC or load the hotfix to allow your 2003 DC to host the Powershell.
Active Directory Script Center
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Have you considered using either PowerShell
So far we've been posting PowerShell. So I'm not sure what you're getting at. The query time limit is on the AD side so no matter what tool you use it will be subject to the limit. But it is possible that other tools would be more efficient and so run the query faster.
skbarnardAuthor Commented:
I have been using PowerShell, the commands above in this thread are the commands I'm using.  Thanks for the links Detlef001 - I had seen the AD Scripting gallery.  Either I didn't use the correct words for my search or nothing was found that completly fit my needs.
I have about 400 more students that don't have the mail attribute on their accounts and for whatever reason, the script is now erroring out with this error
The term 'mail=\.name*' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
This script worked for the lion share of the students.  I can add the mail attribute manually to the remaining students but I'd really like to not have to do that.
Any thoughts
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
That's a syntax error you're getting. Make sure you have all the parenthesis and quotes correct.

If you like you can post the command verbatim and I'll see if I can point out the issue.
skbarnardAuthor Commented:
I've run this command several times and I believe it's iterating through the whole OU, not just finding the users that don't have a mail attribute.
The code below is generic and is what I used; I changed no quotes or parenthesis - just changed the OU, DC and the domain after the '@' for the email domain.
It worked on the lion share of the users; I only have about 1,000 more (from about 33,000)

Get-ADUser -LDAPFilter "(!(mail=\.name*))" -resultSetSize $null -searchbase "ou=test,dc=nwtraders,dc=com"| % {set-aduser -identity $_.distinguishedname -email ($_.samaccountname + "")}

I was just now trying to import a .csv file that I have concatenated the user name with the "".  I've named that column "UserEmail".
I don't get an error when I use the Import-CSV ($Udata = Import-Csv .\UserData.csv), but I also don't know if it truly imports - it comes back to the [PS] prompt.  So I actually tried the command on one line

$Udata = Import-Csv .\UData.csv | foreach {($user in $Udata)Set-ADUser -Identity $user.sAMAccountName -Filter Mail = $user.UserMail}

I get this error: Unexpected token 'in' in expression or statement.

I think what I need is to know the syntax to put this at a powershell script instead of trying individual command and then run the .ps1 script.

Can anyone give me the necessary syntax to put the logic in the script to iterate through my .csv file and write the data from the "UserEmail" column to the LDAP mail attribute?
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Get-ADUser -LDAPFilter "(!(mail=\.name*))" -resultSetSize $null -searchbase "ou=test,dc=nwtraders,dc=com"| % {set-aduser -identity $_.distinguishedname -email ($_.samaccountname + "")}

Open in new window

This looks correct. Are you sure you're getting an error when running this?
I don't get an error when I use the Import-CSV ($Udata = Import-Csv .\UserData.csv), but I also don't know if it truly imports
You can see what was imported by typing the variable and pressing enter at the prompt. i.e. $Udata <enter>

$Udata = Import-Csv .\UData.csv | foreach {($user in $Udata)Set-ADUser -Identity $user.sAMAccountName -Filter Mail = $user.UserMail}
Well there's several things wrong with this but you're trying to use the variable before it's set and that's why it's throwing the error.

When you import a CSV file, the data is put into properties of the column header names. So if you have columns "sAMAccountName" and "UserMail" and you import it to the $Udata variable, you can then loop through the CSV. So for your code there you could do something like this:
$Udata = Import-Csv .\UData.csv 
foreach($user in $Udata){
    Set-ADUser $user.sAMAccountName -EmailAddress $user.UserMail

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
skbarnardAuthor Commented:
Thank you so much, that's the direction I needed to make this run properly.  I did have to put the "foreach" construct on one line and the name column in my .CSV file was just "Name" so I had to change that criterion to $
Jeremy WeisingerSenior Network Consultant / EngineerCommented:
Glad to help.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.