Link to home
Start Free TrialLog in
Avatar of kontrariankid
kontrariankidFlag for United States of America

asked on

Modify Group attributes using CSV input file.

Good evening,

I think I have wasted enough of one day. I have not been able to find any script close to this, except for modification of user accounts. There are vague references to Powershell solutions which will be great if that is what is needed, but I am hoping for a VBS solution. I am being put into a situation where I am essentially being forced to learn scripting.

I need to edit this to use the sAMAccountNames in the input file to query over 1,700 groups (distribution lists) and MODIFY the displayName, distinguishedName, CN, as well as the sAMAccountName. The output file results in generated text but it seems it is simply output; not an indication that groups were modified. The displayNames are blank currently but the distinguishedNames and the sAMAccountNames have values. I was told that after querying for the sAMAccountName, I could change the line or add a line to query and bind to for CN, in order to modify the sAMAccounNames.

Ideally, I need to remove the "z-" that is used to begin the sAMAccountNames as well as the DN, and CN for all these groups and then use the sAMAccountNames to write the vaules for displayNames with (XXXX) after them.. and then "establish email addresses" by specifying the second part of the SMTP address to be @xxx.xxxxx.xxx. But I would be content for now just to get a solution for the first paragraph. Thank you!

Dim objConnection,objCommand,objRootLDAP,strDNSDomain,strUserorMachine
DIM OldName

On Error Resume Next

'file constants
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

'LDAP Constants
Const ADS_SCOPE_ONELEVEL = 1
Const ADS_SCOPE_SUBTREE = 2
Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
Const ADS_PROPERTY_CLEAR = 1

Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objConnection.Cursorlocation=3

Set objCommand =   CreateObject("ADODB.Command")
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000

Set objRootLDAP = GetObject("LDAP://RootDSE")
strDNSDomain = objRootLDAP.Get("DefaultNamingContext")

'Here read from the source file to get a sAMAccountName and then loop for each one

strInputFile = inputbox("Please enter the Mapping File", "Input")
'This will be the extract of sAMAccountName


strOutputFile = inputbox("Please enter the Output File", "Input")
'This will be the resulting output file that contains the Accounts processed


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile(strInputFile, ForReading)
Set objFile = objFSO.GetFile(strInputFile)

If objfso.fileexists(strinputfile) then

Set objCreateFile = objFSO.CreateTextFile(strOutputFile)
objCreateFile.Close


'check to see if the file is empty
If objFile.Size > 0 Then
   
Do Until objTextFile.AtEndOfStream
    strNextLine = objTextFile.Readline
    arrUidList = Split(strNextLine , "*")

'here we set the ldap query

objCommand.CommandText= "<LDAP://dc=XXX,dc=XXXXX,dc=XXX>; (&(objectclass=group)(sAMAccountName=" & arrUidList(0) & ")); name,cn,distinguishedName,displayName;subtree"

Set ObjRecordSet = objCommand.Execute

'Bind using distinguishedName

While Not objRecordSet.EOF
      strUserDN=objRecordSet.Fields("distinguishedName")
      strcovname=objRecordSet.Fields("Name")

'go to the next looked up uid but there should never be one
objRecordset.MoveNext

Wend
'Enable the Account

set objUser = GetObject("LDAP://" & strUserDN)

'can set the displayName to specified value in file
'objuser.displayname= arrUidList(1)
'objUser.SetInfo

'this appends a value to existing displayName
'be sure and test with sample file                                  

'option to update sAMAcountName using second column in mapping file
'objuser.sAMAccountName=arrUidList(1)

OldName = objuser.displayname
objuser.displayname = OldName & " (XXXX)"
OldNamecn = objuser.cn
objuser.cn = OldNamecn & " (XXXX)"
objUser.SetInfo

Set objOutputFile = objFSO.OpenTextFile(strOutputFile, ForAppending, True)
'Here we would output the variables that we looked up

objOutputFile.WriteLine(strcovname & "," & objuser.displayname & "," &  objuser.cn)
objOutputFile.Close

OldName = ""
OldNamecn = ""
strcovname=""
strUserDN=""
arrUidList = ""

'end of read loop
Loop


'finalize the connection
objConnection.Close


' if the file was empty let us know
Else
    Wscript.Echo "The file is empty."
End If


Wscript.echo "Accounts Updated!"

Else
    Wscript.Echo "Mapping file does not exist."
End If
Avatar of yo_bee
yo_bee
Flag of United States of America image

So if I am understanding your situation.
You want to change DN,SAM and CN?
So you want to query all users and replace ZZZZ with XXXX.
What error and line is this failing?
Avatar of kontrariankid

ASKER

Good morning yo_bee. Thanks for replying. For clarification, I just placed the XXXXs to keep company identity hidden. Actually, the DN, SAM, and CNs do have values such as "z-Brambleton" for example. So the values for attributes DN, SAM, and CN are all the same, say "z-Brambleton". After all is complete, this is what needs to happen:

distinguishedName = CN=Brambleton (XXXX),OU=XXXX,OU=Distribution Lists,OU=Enterprise Production,DC=xxx,DC=xxxxxx,DC=xxx
cn = Brambleton (XXXX)
displayName = Brambleton (XXXX)
sAMAccountName = Brambleton

So of the four, the displayName is currently the only empty attribute and needs to be populated with the same value of the SAM + (XXXX). In other words, I need to concatenate or append " (XXXX)" to each of the displayNames AND the CNs, so the old names for example "z-Brambleton" must become "Brambleton (XXXX)".

Lastly, I need to email enable-enable these, same as right-clicking, Exchange tasks, Establish E-mail Address on Groups. The SMTP address would become Brambleton@xxx.xxxxxx.xxx.

I will try to keep on top of this today to provide any further feedback for you in case you are not sleeping at this time. Thank you.
is your Domain XXXXXX.XXX?
The domain is the entire xxx.xxxxxx.xxx. (Actually, the SMTP suffix needs to be "aaa.xxxxxx.xxx" whereas it defaults to xxx.xxxxxx.xxx when email-enabling an account manually.) Also, looking again at your reply last night, the script does not appear to fail, because it writes to the output text file, but it DOES FAIL because it is not updating the three test accounts I have in the input file.

INPUT FILE, example:
z-Brambleton
z-Crambleton
z-Drambleton

OUTPUT FILE, example:
z-Brambleton, (XXXX),z-Brambleton (XXXX)
z-Crambleton, (XXXX),z-Crambleton (XXXX)
z-Drambleton, (XXXX),z-Drambleton (XXXX)

OUTPUT SHOULD BE:
Brambleton,Brambleton (XXXX),Brambleton (XXXX)
Crambleton,Crambleton (XXXX),Crambleton (XXXX)
Drambleton,Drambleton (XXXX),Drambleton (XXXX)

I think this is in the format of "name, displayName, cn", based on this line:
objOutputFile.WriteLine(strcovname & "," & objuser.displayname & "," &  objuser.cn)
Is that correct? And what is "name" attribute exactly?
What I am asking is if the XXX are real part of the DC=,DC= or is it just a replacement for posting on this forum?
The original question that I inquired was does it error and if so what line?
Ah. No it is not real.. the xxx's are for concealment purposes since this is publicly accessible.
Understood.
can you use contoso.com as the domain?
Ok. Sure. And no, it does not error. Refer to my comment Posted on 2012-04-10 at 10:25:55ID: 37827889
Name is the how AD/LDAP displays it in the MMC.

For example:
Display name is  SN, & CN
Where Name could be CN & SN
Ah. So 'name' is a combination of attributes, even though it is also itself an attribute? Makes sense. Any thoughts as to why the script is not modifying the intended accounts as provided by the input text file?
Not 100% sure.
I know when you create a new user object in AD the wizard asks for the First, Middle Initial and Last.
during this process you will notice that the Full Name field is populated.
This populated field are the same initial values as Display Name and Name and CN.

You can change the display name to be Last, First (which is SN, CN)
This will not change the Name attribute.

You can also have the Full name default to SN, CN by modifying the Schema User object.  This is would then by default set the displayname, CN and Name to SN, CN.
Hmm. Those are not available options. I cannot change anything to do with Schema or the way that displayName is defined. Our domain services over 70 different organizations and the OPS team handles such tasks anyhow. I am a part of the migration team.
Once the DisplayName or Name is created it will not use the CN or SN values.
They are their own attribute at that point.

So you are looking to create a CSV file with the audit of the original DN, CN and Name then update the values and then append those values.

Is that correct?
Yes. That sounds correct; although the displayName and cn are appended only with the " (XXXX)", as should be specified by these lines:

OldName = objuser.displayname
objuser.displayname = OldName & " (XXXX)"
OldNamecn = objuser.cn
objuser.cn = OldNamecn & " (XXXX)"
objUser.SetInfo
Ok
You want the (xxx)  brackets in the name.  
I am not sure how this will work.
I will test on when I get home.
Yes. Output should be in this format.. Brambleton, followed by one space and then the (XXXX), like so..

Brambleton,Brambleton (XXXX),Brambleton (XXXX)
Crambleton,Crambleton (XXXX),Crambleton (XXXX)
Drambleton,Drambleton (XXXX),Drambleton (XXXX)
you_bee, Thanks for your diligent efforts. At this point, I don't care what script type is used. Whether it is PS, VB, batch.. as long as it reads from an input file and actually modify the DLs to desired output per above details.
I will get you something by morning?
SOLUTION
Avatar of yo_bee
yo_bee
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
yo_bee, I apologize for the delay. I was instructed to assist with other tasks today. Here is the output that your script produced:

Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

DC=xxx,DC=contoso,DC=com
CN,Name,DN,NewDN
No groups ?
correct. no groups. when the input box popped up, i typed "z-" and hit ok.
are you putting the *?
no. oops! i will try again using z-* in the input popup.
it produced 1,000 lines of output, but i forgot to change the XXXX to the organization code, and it did not put a space in front of the (XXXX). trying to understand what i need to change or undo.
this code just output currently I did not want to run the update portion until the output looks correct.
ok good thing you put that precaution in there. thank you. i see that nothing was modified yet. this is an example of one of the lines of output. when it is complete, it should look something like this: Brambleton (xxxx); not this: Brambleton(xxxx). so this "(xxxx)") should be changed to this right: " (xxxx)") ?

CN=z-Brambleton,z-Brambleton,CN=z-Brambleton,OU=VDOT,OU=Distribution Lists,OU=Enterprise Production,DC=xxx,DC=contoso,DC=com,CN=z-Brambleton(xxxx),OU=VDOT,OU=Distribution Lists,OU=Enterprise Production,DC=xxx,DC=contoso,DC=com
leaving office now. will be home in two hours or so if i need to respond again. thank you yo_bee. i actually already updated most of the groups displayName attribute with the (XXXX), using ADModify. i used this also to add an SMTP address of "aaa.contoso.com" and make that the Primary SMTP address, but it seems that all of the accounts were not updated. many still reflect the old primary SMTP address. it seems "hit and miss". so if i use this script to update all, i will need it to REPLACE the current displayName rather than appending anything which could result in "Brambleton (XXXX) (XXXX)". at any rate, i will still be able to use the script to rename from "z-Brambleton (XXXX)" to "Brambleton (XXXX)" or from "z-Brambleton" to "Brambleton (XXXX)".
Play around with the attributes yourself for a while and see what you can learn from this.
I am here to assist if need be.

The one issue you will with wanting this as a CSV rather than a tab delimited is that the DN will be split.
True! I do not need it to be a CSV. I apologize if I made that impression. Can I use a tab delimited instead? You are referring only to the output though, correct? Also, what changes must be made to the script in order to produce modifications to the groups?
Objuser.put "attribute", value
Objuser.setinfo.

I would not do that just yet.  I would first change the output file to a tab delimited run a find and  Replace "," with vbtab.
Change the output.csv to output.txt
Do I simply need to replace this portion wscript.echo? But what must it be replaced with? Or maybe you will be providing more input after I discover more?
Ah. Thank you. I do see where you commented out the "Objuser". So "Objuser.put" is actually the command that causes modifications? This was missing from my original script that I posted. Maybe that was a big problem? Or is "Objuser.put" only one modification command?

I see where this...
Objuser.put "attribute", value

Refers to...
'objuser.put "name",  stroldName & " (XXXX)"
'objuser.put "cn", stroldCN & " (XXXX)"
'objuser.put

But I do not see "Objuser.setinfo" anywhere in your script. What is that?
how are things going?
Your next step is to build a test.  
Once you click the button you may want to revert back.
Once in place and you run it, you need to know you can get yourself out.

So what I would do now is either build a Virtual Domain.
You can do this with free tools.

Do you have a box you can build it on this would be a good tool for future projects.
If so I would Download Windows Server 2008 R2 with Service Pack 1  trial add the Hyper-V role (Hyper-V Getting Started Guide).

Once you have it built you can use that same trial for your new AD and test your AD attribute project.

If not I would add a Test_OU to your AD and create 5 or so accounts and test on them.

You did have the Put, Setinfo as part of your script, but it was remarked out.

set objUser = GetObject("LDAP://" & strUserDN)

'can set the displayName to specified value in file
'objuser.displayname= arrUidList(1)
'objUser.SetInfo
Thanks yo_bee. I cannot run anything at the moment because I upset our FIM guy yesterday when using ADModify to update primary SMTP addresses. He was concerned that I might "take down FIM".

I have used VM Workstation before but currently have Windows 7 and do not have local admin rights on my own laptop because until the Security team figures something out for our team. I do have a test workstation in the domain that I can probably install a VM on.

I do have an OU that I can use to isolate for this purpose.

Will let you know when I have the green light to modify more accounts. But I probably will not be able to do anything else until tonight.
What were you updating?
I was updating the primary SMTP address, but using ADModify, it was hit and miss. So I first tried to remove a proxyaddress of @bbb.contoso.com, and after confirming on a few accounts thta it was removed, I THEN updated the primary SMTP address with the desired @aaa.contoso.com value. I was also able to update displayName on these z- accounts to add " (XXXX)". But it still seemed to be hit and miss.

Now I am being told by OPS that they plan to run processes this weekend, so they are telling me I cannot update the required hundreds of accounts until Monday after COB.

This is the output produced after replacing "," with vbtab:

CN=z-Group_Name      z-Group_Name      CN=z-Group_Name,OU=XXXX,OU=Distribution Lists,OU=Enterprise Production,DC=aaa,DC=constoso,DC=com      CN=z-Group_Name (XXXX),OU=XXXX,OU=Distribution Lists,OU=Enterprise Production,DC=aaa,DC=contoso,DC=com

Is this the line that produces above output?
wscript.echo StrOldname & vbtab & stroldcn & vbtab & stroldDN & vbtab & ReplaceTest(strOldCN, stroldCN & " (XXXX)")

If so, then I can see that this is outputting as such...
Old-name   Old-cn   Old-distinguishedName   (ReplaceTest(stroldCN, stroldCN & " (XXXX)")

                                                      ^^^^^^^^
                                                      But I am trying to understand the purpose of this function. Is this only for testing purposes?

I need also to update the displayName, so I edited as such ok?

added this line after line 47:
      strolddisplayName = objuser.displayName

and added this line after line 52:
'objuser.put "displayName", strolddisplayName & " (XXXX)"
You can also use Exchange System manager > Policies to push an addition address to all AD objects.

To address the question at hand:
Are you asking what this Replacetest is being used for?

ReplaceTest(strOldCN, stroldCN & " (XXXX)")
Yes sir. I was curious about that ReplaceTest.

I ran your script against only one account and this is the resulting output (without my added line to update displayName):

>cscript EE_Group-Modify.vbs > EE_output.txt
D:\VDOT_DLs\EE_VDOT-DL-Modify.vbs(54, 1) Microsoft VBScript runtime error: Wrong
 number of arguments or invalid property assignment: 'put'

Per above error message, this is line 54 and 55...
objuser.put
objRS.MoveNext
Since you are pulling the DN down.

"cn=user1,OU=Test,DC=Contoso,DC=com" how would you change the CN=User1 to CN=user1(xxxx) without affecting the entire string?
That is why were are running this Replace function to read the entire script cache it and the run a replace

Does that make sense
What is your ultimate goal here?
Just to add or replace the smtp address?
> What is your ultimate goal here? Just to add or replace the smtp address?

      I would like to replace one smtp address with another and make the new one the Primary SMTP; although that is not necessary the goal of this posting on EE. It is equally as important so would be a nice plus, but not expected.

> That is why were are running this Replace function to read the entire script cache it and the run a replace. Does that make sense

      Yes. So that is the provision that will update the distinguishedName? I was wondering about that. It was not apparent to me how there was a connection being made to distinguishedName. Is line 63 where that is being done as follows?

      str1 = StroldDN

> You can also use Exchange System manager > Policies to push an addition address to all AD objects.

      Are you referring to the Recipient Update Service? I understand I can right-click and choose "Update Now" but it is not my place to run that as our domain includes more than just the accounts that I am working with. We already have a Recipient Policy for "aaa.contoso.com". Anyhow, RUS should have updated my accounts by now, so I think it needs to be done by script at this point.
yo_bee, per Comment ID: 37843351, I commented out line 54 as follows:

'objuser.put

As a result, I did not receive the error mentioned, but the account that I tested was not updated.
I will see what the error  is when I get home
between all the back and forth i lost sight of what attributes you are looking for again

Can you list them?
You might not need to address the DN, but I want make sure.
I think I have been feeding you incorrect info.

We can not use the .put method when dealing with CN renaming.
We need to use the .MoveHere method.

I would try an iron out the MoveHere portion.  You give me all your attributes you would like to change.
Some may MoveHere and some will need the Put method depending on the Attribute you wish to address.
Did you get my last reply?
Hey yo_bee. I'm sorry. I do not remember seeing an email notification that you had replied. The attributes that I need to update are...

      name, cn, sAMAccountName, distinguishedName (unless you discover that it reads from other updated attributes).

This attribute is empty but needs the same value as the others: displayName

Lastly, after I email-enable these DLs, will need to update the Primary SMTP to change from bbb.contoso.com to aaa.contoso.com since it is defaulting to the wrong one.
I just re-ran the script after replacing "put" with "MoveHere" first on line 53 and then on 54 as follows:

>cscript EE_XXXX-DL-Modify.vbs > EE_output.txt
D:\XXXX_DLs\EE_XXXX-DL-Modify.vbs(53, 1) Active Directory: An invalid directory
pathname was passed

>cscript EE_XXXX-DL-Modify.vbs > EE_output.txt
D:\XXXX_DLs\EE_XXXX-DL-Modify.vbs(54, 1) Microsoft VBScript runtime error: Wrong
number of arguments or invalid property assignment: 'MoveHere'
There is more to this.
I will need to play around with it
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I found a solution by editing and adding to a script from "charast", link provided here:

https://www.experts-exchange.com/questions/24743022/VBscript-to-rename-Groups-in-AD.html
by: charast, Posted on 2009-09-21 at 14:18:46ID: 25385811

The key, as "charast" discovered, was using more than one input file, and then reading from the related file(s) as necessary.