Powershell: Add users to group from list surname givenname

janhoedt
janhoedt used Ask the Experts™
on
Hi,

I need to add users to an ad group based upon a list a user provide me. Of course in a format which is useless to me:
surname givenname
surname givenname
...

How can I convert this into samaccountnames so I can easily add the users to a group?

Please advise.
J.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
Got something here but would appreciate input.

$users = Get-Content 'C:\userstoadd.txt'
$users
#remove whitespaces in front and at then end, then also make sure there is
#only one whitespace between  family name and firstname (family name is also sometimes more then one or even two words)
#then need to get $lastname and $firstname of each of the users and it should not stop when it does not find the user
#maybe even suggest a name in case it doesn't find the user (spelled differently) but that's a next level wish :-)

Get-ADUser -Filter "Name -like '*$lastname*'" -Properties * | Where {($_.Surname -eq $lastname) -and (($_.GivenName -eq $firstName) -or ($_.DisplayName -like "*$firstname*")) } | Select samAccountName
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
If the list matches AD then you can do something simple like this:

$userlist = "C:\userlist.txt"
Get-Content $userlist | %{Get-ADUser -Filter {name -eq $_}} | select -ExpandProperty samaccountname

Open in new window

Author

Commented:
Got somewhere now, commented what my problem is = selecting family name because it can exist of multiple parts.
Thanks for your input.

$file = 'C:\userlist.txt'
#Remove whitespaces
#The first parameter to -replace is a regular expression pattern to match, and the second parameter is the text that will replace any matches.  \s will match a whitespace character, and + indicates to match one or more occurrences, so, in other words, one or more adjacent whitespace characters will be replaced with a single space. Enter help about_comparison_operators or see here for more information.
$users = (Get-Content $file) | ForEach-Object { $PSItem -replace '\s+', ' ' }

#option familyname first or firstname first
foreach ($user in $users) {
                           $firstname = $user.split(' ')[0]
                           $familyname = $user.split(' ')[1] #PROBLEM HERE IS THAT USER SOMETIMES EXISTS OF 2, 3 OR MORE NAMES f.e. Erica Van Den Bossche, John Wrest Chesterburgh
                           
                           #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
                           Get-ADUser -Filter {displayname -like "$familyname $firstname"} | select -ExpandProperty samaccountname
}

Open in new window

Jeremy WeisingerSenior Network Consultant / Engineer
Commented:
Is there anything we can know about the data in the text file? There's no way to distinguish between middlename and multi part surname but if we know there are no middle names we can deal with it.

Another option would be look through and match based on first and last to see if that's unique enough. Something like this:

$file = 'C:\userlist.txt'
#Remove whitespaces
#The first parameter to -replace is a regular expression pattern to match, and the second parameter is the text that will replace any matches.  \s will match a whitespace character, and + indicates to match one or more occurrences, so, in other words, one or more adjacent whitespace characters will be replaced with a single space. Enter help about_comparison_operators or see here for more information.
$users = (Get-Content $file) | ForEach-Object { $PSItem -replace '\s+', ' ' }

#option familyname first or firstname first
foreach ($user in $users) {
                           $firstnameFilter = "*" + ($user.split(' ')[0]) + "*"
                           $familyname = $user.split(' ') | select -Last 1
                           $familynameFilter = "*" + $familyname + "*"
                           
                           #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
                           Get-ADUser -Filter {givenname -like $firstname -and surname -like $familynameFilter} | select -ExpandProperty samaccountname
}

Open in new window

Senior Network Consultant / Engineer
Commented:
If we know that there's no middle name then you can use this to make the surname:

$familyname = $user.split(' ')
$namecount = $familyname.count - 1
$familyname = $familyname[1..$namecount] -join " "

Open in new window

Author

Commented:
Great thanks! Would you mind clarifying what you are doing there?

Got it partially working now, however, however, some of the users do not resolve because of a comma in the

FirstName  FamilyName         SamAccountame
---------  ----------         -------------
John      {Doe, }                  
Eric        {Whatever, }                    
Wendy      {Ericsson}        wericsson
 Guido      {For,Ever}        

Appreciate your input!

#option familyname first or firstname first
$result = @()
foreach ($user in $users) 
{
  $firstname = $user.split(' ')[0]
  $familyname = $user.split(' ')
  $namecount = $familyname.count - 1
  $familyname = $familyname[1..$namecount]
                            
  #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
  $UserDisplayNameToLookFor = "$familyname $firstname"
                                      
  $samaccountame = Get-ADUser -Filter {
    displayname -like $UserDisplayNameToLookFor
  } | Select-Object -ExpandProperty samaccountname
  
  $result += [pscustomobject]@{
    FirstName         = $firstname
    FamilyName = $familyname
    SamAccountame = $samaccountame
    
  }
}

Open in new window

Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
You can use wildcards and/or filter on the givenname and surname properties.

Wildcard against the Displayname:
#option familyname first or firstname first
$result = @()
foreach ($user in $users) 
{
  $firstname = $user.split(' ')[0]
  $familyname = $user.split(' ')
  $namecount = $familyname.count - 1
  $familyname = $familyname[1..$namecount]
                            
  #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
  $UserDisplayNameToLookFor = "*$familyname $firstname*"
                                      
  $samaccountame = Get-ADUser -Filter {
    displayname -like $UserDisplayNameToLookFor
  } | Select-Object -ExpandProperty samaccountname
  
  $result += [pscustomobject]@{
    FirstName         = $firstname
    FamilyName = $familyname
    SamAccountame = $samaccountame
    
  }
}

Open in new window

Wildcard against the given name and surname:
#option familyname first or firstname first
$result = @()
foreach ($user in $users) 
{
  $firstname = $user.split(' ')[0]
  $gnfilter =  "*" + $firstname + "*"
  $familyname = $user.split(' ')
  $namecount = $familyname.count - 1
  $familyname = $familyname[1..$namecount]
                            
  #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
  $snfilter = "*$familyname*"
                                      
  $samaccountame = Get-ADUser -Filter {
    givenname -like $gnfilter -and surname -like $snfilter
  } | Select-Object -ExpandProperty samaccountname
  
  $result += [pscustomobject]@{
    FirstName         = $firstname
    FamilyName = $familyname
    SamAccountame = $samaccountame
    
  }
}

Open in new window

Author

Commented:
Solved it this way

  $familyname = $familyname[1..$namecount]
  $familyname = $($familyname -join (' ')).trim()

Author

Commented:
Note: why use wildcard? Want an exact result.
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
If you specify the name with the wildcard surrounding it, that still has to match the whole string but will allow for preceding and trailing characters that are not part of the name like a space or a comma.
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
Glad to help. :)

Author

Commented:
One more thing: What if you put family name first? How would you approach it then?
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
Which are you referring to? The list or the display name?

Author

Commented:
DisplayName
I d like to make this work:
#if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstn...
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
Well you could just reverse the order in your script or if you need to check for both use an -or operator and match against both. But I would not even bother with the display name. Filter against the givenname and surname (as I was doing) and then the displayname doesn't matter.

  $samaccountame = Get-ADUser -Filter {
    givenname -like $firstname -and surname -like $familyname
  } | Select-Object -ExpandProperty samaccountname

Open in new window

Author

Commented:
Thanks! Problem though is again the family names consisting of multiple parts ....
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
So is the family name not going to be entered in the surname/last name attribute? Event if it's multi part it should still match. The only issue is if it's in other attributes and not in the lastname field.

Author

Commented:
Not sure I'm getting what you are saying.
The function needs the parameters -lastnamefirstname for reversing the logic right?
Jeremy WeisingerSenior Network Consultant / Engineer

Commented:
I'm saying to not look at the displayname at all. Look at the givenname (First name) and surname (Last name). So you don't need to know the order that the display name is in.

I've posted several variations on this:
  $samaccountame = Get-ADUser -Filter {
    givenname -like $firstname -and surname -like $familyname
  } | Select-Object -ExpandProperty samaccountname

Open in new window

Do you have any questions on what this is doing?

In this script the order of the display name doesn't matter. It will just look at the first and last name:
$result = @()
foreach ($user in $users) 
{
  $firstname = $user.split(' ')[0]
  $gnfilter =  "*" + $firstname + "*"
  $familyname = $user.split(' ')
  $namecount = $familyname.count - 1
  $familyname = $familyname[1..$namecount]
                            
  #if familynamenamefirst $name = "$familyname $firstname" else $name = "$firstname $familyname"
  $snfilter = "*$familyname*"
                                      
  $samaccountame = Get-ADUser -Filter {
    givenname -like $gnfilter -and surname -like $snfilter
  } | Select-Object -ExpandProperty samaccountname
  
  $result += [pscustomobject]@{
    FirstName         = $firstname
    FamilyName = $familyname
    SamAccountame = $samaccountame
    
  }
}

Open in new window

Author

Commented:
Let me check what is actually doing in powershell.I ll understand beter then.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial