• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1579
  • Last Modified:

Active Directory user attributes update

I recently discovered I need to fill in First Name and Last Name attributes for all my active directory users.  We do have Display Name filled in.  I have 40,000 users and don't want to do it manually.. is there anyway for me to take Display Name user the first word as First Name and the last word as Last Name?
0
darovitz
Asked:
darovitz
  • 14
  • 7
  • 5
  • +2
2 Solutions
 
Henrik JohanssonSystems engineerCommented:
Script it with ds*-commands (part of adminpak.msi) like below
Variables nead to be prefixed with double %% if copying the command into a cmd-file instead of executing directly in the command prompt
for /F "skip=1 tokens=1,2,3" %a in ('dsquery user "OU=OUchild,OU=OUparent,DC=domainname,DC=local"^|dsget user -samid -fn -ln') do dsquery user -samid %a | dsmod user -display "%b %c"

Open in new window

0
 
darovitzAuthor Commented:
C:\Documents and Settings\melaniep.ph>for /F "skip=1 tokens=1,2,3" %a in ('dsque
ry user "OU=5403,OU=Hosted,DC=g1.projecthosts.com,DC=local"^|dsget user -samid -
fn -ln') do dsquery user -samid %a | dsmod user -display "%b %c"
dsquery failed:A referral was returned from the server.
type dsquery /? for help.dsget failed:`Target object for this command' is missin
g.
type dsget /? for help.
C:\Documents and Settings\melaniep.ph>

Thanks so much but I am not good at code.  I think I need to have something in front or am missing some of the code.  I copy and pasted what you wrote into command prompt.
0
 
darovitzAuthor Commented:
Also I want to do this or my entire active directory so starting at the root domain which is g1.projecthosts.com
0
Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

 
Chris DentPowerShell DeveloperCommented:

This is the problem:

dsquery user "OU=5403,OU=Hosted,DC=g1.projecthosts.com,DC=local

It should be:

dsquery user "OU=5403,OU=Hosted,DC=g1,DC=projecthost,DC=com

It's a bit more complex if you must change things for every domain in a forest, the Global Catalog can be used to retrieve information, but not to write. And you would need to define how you want to filter so it returns only accounts you want to change (since you cannot specify an OU if you're doing the entire forest at once).

Chris
0
 
Henrik JohanssonSystems engineerCommented:
As Chris posted, the error is caused by entering incorrect domain reference.
Domain g1.projecthost.com in LDAP-format is DC=g1,DC=projecthost,DC=com

The OU-part of the path parameter is only necessary if you want to minimize the results of the query to only handle the specified OU instead of whole domain. Change the dsquery command to be 'dsquery user "DC=g1,DC=projects,DC=com"' to reach the whole domain independent of OU-structure.
It's as said more complex to modify whole AD-tree. The easiest solution would propably be to execute the dsquery command against each subdomain

dsquery user "DC=subdomain,DC=g1,DC=projects,DC=com"

I forgot to add the -limit parameter in the previous post making dsquery to only return max 100 records by default.

for /F "skip=1 tokens=1,2,3" %a in ('dsquery user -limit 0 "DC=g1,DC=projects,DC=com"^|dsget user -samid -fn -ln') do dsquery user -samid %a | dsmod user -display "%b %c"

Open in new window

0
 
eridzoneCommented:
Do this job on per domain basis, starting from root domain use any script that can change attribute with comparing to user name or email address.

i have done this type of task in my environment in which i had to enter employee number in "initial field" as there is no option of employee number, in my case i used a script which first take input from an excel sheet , there were two columns one is employee no and other one is email address, script then  compare email address from sheet to user profile and then finally insert the employee no in the initial field.
0
 
darovitzAuthor Commented:
henjoh09
What the query did was remove all the display names and it did not add it to First Name Last Name.  So now I have a really bad problem as I don't even have display name?
0
 
darovitzAuthor Commented:
It says: Failed target object for this command is missing.

0
 
darovitzAuthor Commented:
So what I need is for the current Display Name to go into the fields First Name and Last Name.  In display name is says something like Jane Blow.  So I want that to remain but to also but Jane in the First Name field and Blow in the Last Name field.
0
 
darovitzAuthor Commented:
C:\Documents and Settings\melaniep.ph>dsquery user -samid Suryanto.Wijaya   | ds
mod user -display " "
dsmod succeeded:CN=Suryanto.Wijaya,OU=3540 PWADesktop,OU=3540users,OU=3540 Disab
led,OU=Hosted,DC=g1,DC=projecthosts,DC=com
0
 
Chris DentPowerShell DeveloperCommented:

Would you consider PowerShell? I've never been any good at batch scripting.

If you will, we need:

http://support.microsoft.com/kb/968929
http://www.quest.com/activeroles-server/arms.aspx

The first gets you PowerShell itself, if you're running 2008 or Windows 7 (or perhaps Vista, I forget) you'll find it installed already or available under "Features" in Control Panel. The second gets you the extremely useful AD CmdLets from Quest. The MS AD CmdLets only work with 2008 R2, and are far less flexible for some unknown reason.

This command (copy and paste into the Quest version of PowerShell) if you want to test with a specific user:

Get-QADUser "SomeTestUser" | %{
  Set-QADUser $_.DN -FirstName $($_.DisplayName.Split[0]) -LastName $($_.DisplayName.Split[-1]) -WhatIf
}

And this if you're happy with what it's up to and want to test on a full set:
 
Get-QADUser -DisplayName "* *" | %{
  Set-QADUser $_.DN -FirstName $($_.DisplayName.Split[0]) -LastName $($_.DisplayName.Split[-1]) -WhatIf
}

Note that I've added -WhatIf. That means the script will run, say what it wants to change, but not actually change anything. Only when you're happy should that be removed.

If you want to change everyone in the forest it becomes:

Get-QADUser -DisplayName "* *" -UseGlobalCatalog | %{
  Set-QADUser $_.DN -FirstName $($_.DisplayName.Split[0]) -LastName $($_.DisplayName.Split[-1]) -WhatIf
}

However, we do need some more filtering there, because that'll capture things like "Launch IIS Process Account",  "Internet Guest Account" and so on.

If displayNames are now blank, we can take the current name value (CN= ...) and repopulate the displayName using that?

Chris
0
 
Henrik JohanssonSystems engineerCommented:
The 'dsget -samid -fn -ln' shall retrieve samid, firstname and lastname. For-parameter tokens=1,2,3 makes the requested columns to be stored in variables %a, %b and %c
0
 
Chris DentPowerShell DeveloperCommented:

fn and ln are the values that need populating rather than display name. Current version copies the two blank values into Display Name by the looks of it.

Chris
0
 
darovitzAuthor Commented:
Chris, I shall try Power Shell as I have been reading about it forever and always wanted to give it a try.  I will get back to you after I start... and thanks
0
 
Henrik JohanssonSystems engineerCommented:
Ouch, re-read the question and see now that it became the opposite compared to the question.
Sorry for I misunderstood it as you wanted to fill display name with the current value of first and lastname. It should had been 'dsget user -samid -display' and 'dsmod user -fn "%b" -ln "%c"'
If it was run against whole domain instead of just an OU, it's definitive a little bit messy...

Is all usernames in same syntax firstname.lastname?
If so, use the powershell script Chris posted, but split the sAMAccountName attribute instead of DisplayName and use "." as separator to populate firstname and lastname.

-FirstName $($_.sAMAccountName.Split(".")[0])
0
 
darovitzAuthor Commented:
It's cool that both you guys are working together.. can you now send the updated script so I can run it.

Thanks,
0
 
Henrik JohanssonSystems engineerCommented:
To fix it with CMD-script and ds-commands:

for /F "tokens=1,2 delims=. skip=1" in ('dsquery user -samid "*.*" ^| dsget user -samid^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"

Scripts should always be tested against a subset, so use it against a sub-OU

for /F "tokens=1,2 delims=. skip=1" in ('dsquery user -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsget user -samid^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"

or let it run in dry mode and only echo to console without executing the command by changing the part after do to be echo and escape the | with ^

for /F "tokens=1,2 delims=. skip=1" in ('dsquery user -samid "*.*" ^| dsget user -samid^|find /i /v "dsget succeeded"') do echo dsquery user -samid %a.%b ^| dsmod user -fn %a -ln %b -display "%a %b"

Splitting dsquery result on "." will cause surrounding spaces in display name, but re-running the command that caused the mess should trim it down when having first and last name attributes entered.


The powershell script modified:

Get-QADUser -sAMAccountName "*.*" | %{
  Set-QADUser $_.DN -FirstName $($_.sAMAccountName.Split(".")[0]) -LastName $($_.sAMAccountName.Split(".")[-1]) -Display $($_.sAMAccountName.Split(".")[0]) + " " + $($_.sAMAccountName.Split(".")[-1]) -WhatIf
}
0
 
Chris DentPowerShell DeveloperCommented:

Thanks henjoh09 :)

We might expand the filter so the script leaves alone anything which already has one of those values set. That would allow a couple of slightly modified scripts to fill in the blanks after a few runs.

Chris
0
 
darovitzAuthor Commented:
First run:

C:\Documents and Settings\melaniep.ph>for /F "tokens=1,2 delims=. skip=1" in ('d
squery user -samid "*.*" ^| dsget user -samid^|find /i /v "dsget succeeded"') do
 dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"
in was unexpected at this time.

C:\Documents and Settings\melaniep.ph>for /F "tokens=1,2 delims=. skip=1" in ('d
squery user -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsg
et user -samid^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | ds
mod user -fn %a -ln %b -display "%a %b"
in was unexpected at this time.
0
 
darovitzAuthor Commented:
How do I know if the powershell is running in Quest:  Also the Display Name does not have a "."  just plain old  Jane Blow

0
 
Henrik JohanssonSystems engineerCommented:
Sorry for the typo, it's missing %a before in
I was propably a little bit sleepy when it was almost 2AM local time...

Whole domain:
for /F "tokens=1,2 delims=. skip=1" %a in ('dsquery user -samid "*.*" ^| dsget user -samid^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"

specific OU-structure:
for /F "tokens=1,2 delims=. skip=1" %a in ('dsquery user -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsget user -samid^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"

OU in dry mode (just echo)
for /F "tokens=1,2 delims=. skip=1" %a in ('dsquery user -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsget user -samid^|find /i /v "dsget succeeded"') do echo dsquery user -samid %a.%b ^| dsmod user -fn %a -ln %b -display "%a %b"
0
 
darovitzAuthor Commented:
That is wicked awesome.  The only issue in testing is it puts two spaces before the display name.
0
 
darovitzAuthor Commented:
It also only works if there is no Display Name at all.  It skipped over the users that did have a display name.
0
 
darovitzAuthor Commented:
One more request.. can you make the first letter cap on first and last name?
0
 
Henrik JohanssonSystems engineerCommented:
The spaces are there caused by each line in the output of dsget is prefixed with spaces and the split was done on "." making the first column with value (%a) to be prefixed with spaces.
The following command should fix the spaces. Added an if-clause to check that the value isn't empty. Added OU-path as default, remove it to affect whole domain.

for /F "tokens=1,2,3* skip=1" %a in ('dsquery user -limit 0 -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^|dsget user -samid -display^|find /i /v "dget succeeded"') do if not "%b"=="" dsquery user -samid %a | dsmod user -display "%b %c"

That it skipped users that had display name set sounds like they don't have a "." in the samid/sAMaccountname attribute (pre-windows 2000 logon name in ADUC)
It can also have been caused by forgetting the '-limit 0' parameter resulting dsquery to only process 100 records. Was there users that wasn't messed up in the earlier run?

for /F "tokens=1,2,3 delims=. skip=1" %a in ('dsquery user -limit 0 -samid "*.*" "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsget user -samid ^|find /i /v "dsget succeeded"') do dsquery user -samid %a.%b | dsmod user -fn %a -ln %b -display "%a %b"

If there was users that wasn't messed up with the original run when emptying display name by mistake, rewrote the command line to have it split the display name to be stored as first and lastname.

for /F "tokens=1,2,3 skip=1" %a in ('dsquery user -limit 0 "OU=5403,OU=Hosted,DC=g1,DC=projecthosts,DC=com" ^| dsget user -samid -display ^|find /i /v "dsget succeeded"') do if not "%c"=="" dsquery user -samid %a | dsmod user -fn %b -ln %c


Capitalizing is a little bit trickier in cmd-scripting than just using a oneliner. It looked like samid already was that in the output you posted earlier.
It would be easier to do in intelligenter scripting language like vbs or powershell. Chris, can you assist with doing the capitalizing in powershell?

/Henrik
0
 
Chris DentPowerShell DeveloperCommented:

To run PowerShell... either start it from the Quest menu under your Start menu, or when you're inside PS run this command:

Add-PsSnapIn Quest.ActiveRoles.ADManagement

It'll throw an error if it's already loaded, so if it does don't worry.

Breaking the PS script up a bit, still copy and paste, and still using "WhatIf" to make sure it doesn't do anything unexpected.

Chris
Get-QADUser -sAMAccountName "*.*" | %{
  # Get the first and last names
  $First = $_.sAMAccountName.Split(".")[0]
  $Last = $_.sAMAccountName.Split(".")[-1]

  # Quick capitalisation, shame it's such a long line.
  $First = [Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase($First)
  $Last = [Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase($Last)

  # Tell us about the change
  Write-Host "$($_.Name): First: $First Last: $Last Display: $First $Last"

  # Make the change
  Set-QADUser $_.DN -FirstName $First -LastName $Last -Display "$First $Last" -WhatIf
}

Open in new window

0
 
darovitzAuthor Commented:
Perfect and thanks for all the effort guys.
Melanie
0
 
Berkant20Commented:
See this code

'############################################
'#
'#	Update Display Name
'#  
'#  
'#  
'#  Update display name
'#
'#
'#
'#
'#	
'#	Berkant DURU
'#	Version:		V1
'#	Création:		19/04/2007
'#	Modification:	25/01/2008 convertion du script pour les display name
'#
'############################################
'#########################
'#	Constantes
'##########################

Const ADS_PROPERTY_APPEND 	= 3
Const ADS_NAME_INITTYPE_GC	= 3 
Const ADS_NAME_TYPE_NT4 	= 3 
Const ADS_NAME_TYPE_1779 	= 1
Const ADS_PROPERTY_DELETE 	= 4  
Const UF_WORKSTATION_TRUST_ACCOUNT 	= &H1000
Const UF_ACCOUNTDISABLE 	= &H2
Const UF_PASSWD_NOTREQD 	= &H20




'VARIABLES GLOBALES
Dim strLDAPPath
Dim objLogFile, objRollBackFile
Dim DefaultsUsername
Dim i
Dim line,matricFiles
Dim filename, objRootDSE, objOU, filecontents,objFileMartic
Dim oFS, oTextStream,sGroup,rep
Dim strUser 
Dim objTrans, objTrans1
Dim strUserDN
Dim oADS
Dim nombank
Dim newdisplay
Dim domName

	i=1
	j=0




	'VARIABLES LOCALES
	Dim strFilePath, objFSO, objFSO1,objFile, strUPN, sMatric, strPIDF, strLastName, strFirstName,numsemaine
	Dim strTitle, strDisplayName, strOffice, stremail, strdept, strDescription, titre

	strFilePath="c:\users.txt"
	matricFiles = INPUTBOX ("Enter a user file name :","Import File Name","c:\users.TXT")
	If matricFiles = "" then
		Wscript.Echo ("Nobody file find")
		Wscript.Quit
	end If
		domName= INPUTBOX ("Enter the domain name:","Domain Name")
	If domName= "" Then
		Wscript.Echo ("Nobody name find")
		Wscript.Quit
	end if
 
Set objFSO = CreateObject("Scripting.FileSystemObject")  	

Set objFileMartic = objFSO.OpenTextFile(matricFiles, 1) 	
Do Until objFileMartic.AtEndOfStream
	sMatric = objFileMartic.readline


	'Initialisation de l'objet de translation de nommage
	Set objTrans = CreateObject("NameTranslate") 
	objTrans.Init ADS_NAME_INITTYPE_GC, "" 
	
	On Error Resume next
	'On récupere le distinguish name de l'utilisateur et du groupe
	Set oADS = objTrans.Set(ADS_NAME_TYPE_NT4, domName &"\"& sMatric)
	if err.Number < 0 Then 
		WScript.Echo (""&i &":  The user "&sMatric &" is not find in AD")
	Else
	WScript.Echo (""&i &":  the user "&sMatric &" is in the AD")
	
	End if
	Err.Clear
	struserDN = objTrans.Get(ADS_NAME_TYPE_1779) 
	

	'Interrogation de l'AD et récuperation de l'objet utilisateur
	set objUser = GetObject("EDMS://"& struserDN)
	if err.Number <> 0 Then 
		WScript.Echo ("The user "&sMatric &" is not find in AD")
		
	Else
		olddisplay=objuser.get("displayName")	
		newdisplay=olddisplay & " " &nombank
		objUser.Put "displayname",newdisplay
		objUser.Put "name",newdisplay
		objUser.SetInfo
		WScript.Echo ("OK "& sMatric &" Updated " &struserDN)
End if
	Err.Clear

i=i+1

Loop
	Wscript.Echo ("End of Script")
'#########################
'#	Fin du script
'##########################

Open in new window

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 14
  • 7
  • 5
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now