I m trying to use a PowerShell script to ask for name and last name and then display the samAccountname I tried this and it did not work.
$Names = Read-host "Jack Robinson"
$Usernames =
Get-ADUser -Filter "FirstName -eq $($_.FirstName) -and Surname -eq $($_.LastName)" -Properties 'SamAccountName' |
Select-Object -ExpandProperty 'SamAccountName'
In terms of taking input from a csv see #wasif Hasan's helpful answer. In terms of your particular code with no csv input - you are better off separating your request for first name and surname with two read-host requests. Take note of the attribute names GivenName for firstname and Surname for Last name
$firstname = read-host "first name"
$LastName = read-host "LastName"
Get-ADUser -Filter "GivenName -eq '$FirstName' -and Surname -eq '$LastName'"|
Select-Object -ExpandProperty 'SamAccountName'
Alternatively if you are unable to double the read-host requests as shown above you can attempt to filter on displayname which usually consists of firstname and lastname
$name = read-host "name"
Get-ADUser -Filter "Displayname -eq '$Name'"|
Select-Object -ExpandProperty 'SamAccountName'
Not sure why you used the pipeline variable when you are not taking input from anywhere. Also in AD user object Firstname is called GivenName and Lastname is called Surname. If you are taking input from csv like this:
FirstName,LastName,
xxx,xxx,
...
then try this:
$usernames = Import-Csv "filepath.csv" -Header GivenName,Surname -Delimiter "," | ForEach {
Get-ADUser -Filter {GivenName -like $_.GivenName -and Surname -like $_.Surname} | Select-Object -ExpandProperty sAMaccountName
}
I assume "Jack Robinson" is supposed to be a sample input. As you have it, it is the prompt that Read-Host will show the user. You probably want something like this:
$Names = Read-Host "Enter the name"
Separating the first and last names based on spaces is never foolproof, especially in cases of two or three-word last names. So you should either separate the prompt into first and last, like Itchydon's answer shows, or you can use ambiguous name resolution (ANR), which would let you search by the full name. That would look something like this:
$Names = Read-Host "Enter the name"
$Usernames =
Get-ADUser -LDAPFilter "(anr=$Names)" -Properties 'SamAccountName' |
Select-Object -ExpandProperty 'SamAccountName'
Searching by first and last name is never an exact science, since you could have multiple people in your organization by the same name, but ANR does make that a little worse because it does a "contains" kind of search. So if you search for my name, "Gabriel Luci", for example, you would also find "Gabriele Luciano".
It just depends on your use. If your user will be picking the right account, then ANR is an easy way to find accounts. But if this is part of some automation where you want to match names exactly, then you will have to split up the first and last names at the input and search for exact matches.
Related
My Get-ADComputer script gives too much information. I would like to shorten it out a little.
$Computer = Read-Host -Prompt 'Input computer name'
$ManagedBy = Get-ADComputer $Computer -Properties ManagedBy |
foreach { $_.ManagedBy }
Write-Output $ManagedBy
When I tried to run my scrip it gives this to output
CN=Last Name First Name ,OU=XX ,OU=XXX ,OU=XXX ,DC=XXX,DC=XXX
I would like to get only CN in the output (First name and Las Name).
Your code returns the distinguished name of the computer's manager. You can use that DN to query the AD user object and obtain the desired properties from that (like FullName, or DisplayName, or the individual values FirstName and LastName).
Get-ADComputer $Computer -Properties ManagedBy |
Select-Object -Expand ManagedBy |
Get-ADUser -Property FullName |
Select-Object -Expand FullName
Firstly have you looked at the objects properties?
These Properties are auto assigned to the variable, when created.
You can see them with:
$ManagedBy | Get-Member
You may well find that $ManagedBy.Name will give exactly what you want.
Further reading for you: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-member?view=powershell-6
I have a list of names taken from Oracle that Im trying to find the SamAccountName for. The file is a CSV and some names are "last, first" or "last, first middle initial" and some have three or four names like "alpha bravo charlie delta". The names in the list are likely not the same as listed in AD. Trying to figure out how to sort through this to find AD accounts. The code I currently have is not producing any results.
Import-Module ActiveDirectory
Import-Csv "\\server\users\folder\Oracle_HR.csv"
ForEach-Object{
Get-ADUser -Filter { Name -like "'$($_.name)'"} -Properties Name |
Select-Object Name,SamAccountName |
Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation
}
The answers by Gabriel Luci and Mathias R. Jessen give good advice on "fuzzy" filtering of AD users.[1]
However, your primary problem is that your ForEach-Object call is not receiving pipeline input, because you haven't connected it to output from the Import-Csv call.
Simply join the two commands with |:
Import-Csv "\\server\users\folder\Oracle_HR.csv" | ForEach-Object { # ...
Secondarily, your -Filter argument { Name -like "'$($_.name)'"} mistakenly applies two layers of quoting and is missing wildcard characters, given that -like compares against the entire field, yet you want substring matching.
Since it's better to avoid the use of script blocks ({ ... }) as -Filter arguments, use a string:
"Name -like `"*$($_.name)*`"" # Note the enclosing '*' to match substrings
Note that I've used embedded " quoting (escaped as `") rather than ' quoting, so as not to break the filter with names that contain ', such as O'Malley.
That said, if, as your question suggests, the names in your CSV data aren't direct substrings of the AD users' .Name property values, the above filter will not be enough, and even the ANR (Ambiguous Name Resolution) technique shown in the linked answers may not be enough.
Thirdly, your Export-Csv call is misplaced: because it is inside the ForEach-Object script block, the same output file gets overwritten in every iteration.
Restructure your command as follows:
Import-Csv ... | ForEach-Object { ... } | Export-Csv ...
Optional reading: ForEach-Object behavior when not providing pipeline input:
The associated script block is executed once.
$_, the automatic variable that contains the current input object, is $null.
[1] Note that the search term in the LDAP filter may need escaping ; per this article, the characters * ( ) \ NUL require escaping and must be escaped as \<hh>, where <hh> is the two-digit hex representation of the char's ASCII code (e.g., * must be escaped as \2A):
$escapedName = -join $(foreach ($c in [char[]] $_.name) { if ('*', '\', '(', ')', "`0" -contains $c) { '\' + ([int] $c).ToString('X2') } else { $c } })
Get-ADUser -LDAPFilter "(anr=$escapedName)"
With $_.name containing string "James* (Jimmy) Smith\Smyth`0", $escapedName would evaluate to literal James\2A \28Jimmy\29 Smith\5CSmyth\00
Keep in mind that the property names in PowerShell are not named the same as the attributes in AD. The Name property corresponds to both the name and cn attributes in AD (both attributes are always the same).
There is also DisplayName (displayName in AD), GivenName (givenName), and Surname (sn). You could try matching against the DisplayName:
Get-ADUser -Filter "DisplayName -eq '$($_.name)'"
If none of those properties match your data exactly, you will have some trouble. No one thing you do will probably work for every account. Hopefully this is just a one-time job and you can work through them in pieces (try one thing, take out the ones that work, and try something different on the rest).
One thing you can try is using AD's Ambiguous Name Resolution (ANR), which will match a search string against several different attributes and even match a first and last name against givenName and sn. That might work with some in your list. You would use it like this:
Get-ADUser -LDAPFilter "(anr=$($_.name))"
If none of that works, you'll have to split the names (for example, by spaces: $_.name.Split(" ")) and try to match pieces of it to different attributes. You'll have to look at your data and see what works.
One approach is to use the Ambiguous Name Resolution feature in Active Directory.
It'll do fuzzy matching against multiple attributes, like the displayName, Name and mail attributes (among others), so it's pretty good for this exact kind of scenario where you don't necessarily know the order or the names or the full name up front:
Get-ADUser -LDAPFilter "(&(anr=$($_.name)))"
I recommend using LDAPFilter and Ambiguous Name Resolution (anr) with Get-ADUser. The algorithm looks up several name fields in different orders to find matches:
Get-ADUser -LDAPFilter "(anr=John Doe)"
Or modifying your code:
Get-ADUser -LDAPFilter "(anr=$($_.name))"
You could try something like the following:
Import-Module ActiveDirectory
$allUsers = Get-Content "\\server\users\folder\Oracle_HR.csv"
$users = #()
ForEach($obj in $allUsers){
$user = Get-ADUser -Filter { GivenName -like $obj} -Properties Name, samAccountName
if(!$user){
$user = Get-ADUser -Filter { SurName -like $obj} -Properties Name, samAccountName
}
if(!$user){
$user = Get-ADUser -Filter { Name -like $obj} -Properties Name, samAccountName
}
if(!$user){
Write-Host "User $obj could not be found" -ForegroundColor Red
}else{
$users += $user
}
}
$users | Select-Object Name,SamAccountName | Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation
You might need to split the values also like:
Import-Module ActiveDirectory
$allUsers = Get-Content "\\server\users\folder\Oracle_HR.csv"
$users = #()
ForEach($obj in $allUsers){
$objSplit = $obj.Split(",")
foreach($split in $objSplit){
$user = Get-ADUser -Filter { GivenName -like $split} -Properties Name, samAccountName
if(!$user){
$user = Get-ADUser -Filter { SurName -like $split} -Properties Name, samAccountName
}
if(!$user){
$user = Get-ADUser -Filter { Name -like $split} -Properties Name, samAccountName
}
if(!$user){
Write-Host "User $split could not be found" -ForegroundColor Red
}else{
if($users.samAccountName -notcontains $user.SamAccountName){
$users += $user
}
}
}
}
$users | Select-Object Name,SamAccountName | Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation
Two questions, first one is probably quite simple but it's extremely annoying. I'm running a script for AD lookup with the user name variable as an attribute:
[string]$FirstName = Read-Host "User First Name"
[string]$LastName = Read-Host "User Last Name"
[string]$FullName = "*$FirstName* *$LastName*"
write-host
Get-ADUser -Filter {name -like $FullName} -properties * | select-object name, samaccountname | sort-object
read-host "Press Enter to exit"
The problem is that "read host" is interpret as a part of the same command, and the query results appear after the prompt. I'd like to pause the script so the results can be read from the screen before console closes by hitting Enter. I've been experimenting with the brackets or different kind of loops but haven't been able to figure out how this should be done.
My second question is that I want to have samaccountname as a search attribute. Something like this:
[string]$Login = Read-Host "User Login name"
[string]$LoginName = "*$Login*"
The variable should be added to filter similar way the FullName variable is used.
1.)
A better way to pause the script and only continue after input, is to use:
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") > $null
The Query should come after the display of the Get-ADUser, if it still isn't working maybe submit some output examples or try getting the AD-User from Get-ADUser * | Where-Object {$_.Fullname like $Fullname}
2.)I'm not fully understanding your problem here, but if you want to get and User by his login name you can do it like this:
$login = Read-Host "Login name"
Get-ADUser $login | select-object name, samaccountname | sort-object
I managed to fix this myself. For the first question, adding "format-table" to the end of the pipeline closed the command and the script proceeded normally after that.
For the second question, as a workaround I just broke down the query as two separate ones. First one is searching for the full name, and the second one is searching for the login name:
Get-ADUser -Filter {name -like $FullName} -properties * | select-object name, samaccountname | sort-object name | format-table
write-host
Get-ADUser -Filter {samaccountname -like $LoginName} -properties * | select-object name, samaccountname | sort-object name | format-table
Good for you finding a solution to your problem,
I will put here also what I did and maybe you can use it.
First of all the first part:
$FirstName = Read-Host "Please provide the Fist name of the User: "
$LastName = Read-Host "Please provide the Last name of the User: "
$Fullname = "$FirstName $LastName"
$Users= Get-AdUser -Filter {name -like $FullName} -Properties * | Select Name, Samaccountname | Sort-Object -Verbose
Get-AdUser -Filter {name -like $FullName} -Properties * | Select Name, Samaccountname | Sort-Object -Verbose
#$Users
you can uncomment the last user variable to get the results on your screen.
as of your second question you can use the -or so you can search with the $fullname or the $login
$Login = Read-Host "User Login name"
Get-ADUser -Filter {name -like $FullName -or samaccountname -like $Login } -properties *
I would prefer a selection before running the code as I do with my checks on the AD
if you want to send you the code I can do it, I just don't want to put in this answer something different from what you ask.
Can someone please tell me how I can rename sn and givenName of a contact object in active directory?
This is how I query the data in my contacts OU:
Get-ADObject -Filter {(ObjectClass -eq "contact") -and (givenName -like "*myName*") } -Properties sn, givenName -SearchBase "OU=contacts,DC=domain,DC=name"
From Microsoft:
To modify the given name, surname and other name of a user, use the
Set-ADUser cmdlet
My goal is to modify the values of both properties because I have text that is all in lowercase and I was hoping to use something like:
$TextInfo = (Get-Culture).TextInfo
$TextInfo.ToTitleCase("one-two three")
Desired Output: One-Two Three
to get a capital letter for each word.
Some examples would be great.
If you know of a GUI-Tool that does what I need then please share as well.
To change the attributes on a contact AD object you will need to use the Set-ADOject Cmdlet, with the -Replace parameter. Set-ADUser will only set attributes of an AD object of type user.
The following code will take the full name of the contact object, search for it in AD and then change the GivenName, SN and DisplayName to title case.
I have added the DisplayName as this field is not automatically update when you change the first and last name, but you can delete this part if it's not needed.
$fullname = "My Name"
$contact = Get-ADObject -Filter {(ObjectClass -eq "contact") -and (Name -like $fullname)} -Properties * -SearchBase "OU=contacts,DC=domain,DC=name"
$TextInfo = (Get-Culture).TextInfo
$GivenNametoTitleCase = $TextInfo.ToTitleCase(($contact.givenName).ToLower())
$SNtoTitleCase = $TextInfo.ToTitleCase(($contact.sn).ToLower())
$DisplayNametoTitleCase = $TextInfo.ToTitleCase(($contact.DisplayName).ToLower())
$contact | Set-ADObject -Replace #{GivenName=$GivenNametoTitleCase;`
sn=$SNtoTitleCase;`
DisplayName=$DisplayNametoTitleCase;}
I want to find description of computer in AD by specific word that exists in Description.
$username = "test111"
Get-ADComputer -filter {Description -Like 'test111*'} -Properties Description | select Description # this works ok
Get-ADComputer -filter {Description -Like "$username*"} -Properties Description | select Description # shows nothing, no error
How can I make the search using variable?
You could just do a query like this:
$username = "test111"
Get-ADComputer -Filter "Description -Like '$username*'" -Properties Description | Select -Expand Description
I think what was happening is that $username was probably $null since it was not passed to the script block. Changing the -Filter to be using quotes allows the variable to expand properly. Threw and -Expand in there so you just get back a string array instead of an Object array.