Powershell AD lookup by name and samaccountname variables - powershell

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.

Related

Issues with looping - Need help "refining" my code

I've this ps script that I have written myself. It searches for available Active Directory groups with a keyword, and if no keyword is found, it outputs that it cannot find any AD groups, and asks if I'd like to search again. However, the issue I'm facing, is that it outputs that it cannot find any AD groups, even if it does find groups with my keyword...
This be my code:
$group = Read-Host "Which groups would you like to search for?"
$group = $group + "_*"
$groups = Get-ADGroup -Filter {name -like $group} -Properties * | select SAMAccountName, Description
while ($groups -eq $null) {
if ($groups -eq $null) {
Write-Verbose "Did not find any matching groups. Try again" -Verbose
$group = Read-Host "Which groups would you like to search for?"
$group = $group + "_*"
Get-ADGroup -Filter {name -like $group} -Properties * | select SAMAccountName, Description
} else {
if ($groups -ne $null) {
Get-ADGroup -Filter {name -like $group} -Properties * | select SAMAccountName, Description
}
}
}
Now, I know this is probably not that cleanly done, and the formatting could be better... maybe. But I'm having a hard time understanding why it outputs the "try again" message even if results shows up
Thanks!
As commented, the while ($groups -eq $null) already tests for 'nothing found', so you need not test that again inside the loop.
I would suggest a slightly different approach using an endless while loop you break out of if the Get-ADGroup cmdlet returned any results
while ($true) {
$group = Read-Host "Which groups would you like to search for?"
# if the user did not enter an empty of whitespace-only string
if (![string]::IsNullOrWhiteSpace($group)) {
# Get-ADGroup by default already returns these properties:
# DistinguishedName, GroupCategory, GroupScope, Name, ObjectClass, ObjectGUID, SamAccountName, SID
# so in this case, only ask for the extra Description property
$groups = Get-ADGroup -Filter "Name -like '$($group)_*'" -Properties Description
if ($groups) {
# output the two properties
$groups | Select-Object SamAccountName, Description
# and exit the while loop
break
}
}
# once here, you didn't find any groups on the input keyword, so let the user try again
Write-Verbose "Did not find any matching groups. Try again" -Verbose
}
Note:
-Filter should be a string rather than a scriptblock
using -Properties * to ask for all is very wasteful if all you eventually care about is two properties.
comparing to $null can be done better with if($groups) as opposed to if ($groups -ne $null) and if(!$groups) as opposed to if ($groups -eq $null). If you must compare to $null, then better change the order like if ($null -eq $groups)
I used the sub expression operator $() in "Name -like '$($group)_*'", because otherwise, PowerShell will try and expand an undefined variable $groups_. An alternative to this is to use "Name -like '${group}_*'"

Find AD user information with DisplayName

I have a list of displaynames and I need to get their AD informations.
Get-Content "C:\displaynames.txt" |
foreach {
$givenname,$surname = $_ -split ' '
if (Get-ADUser -Filter "surname -eq '$surname' -and givenname -eq '$givenname'"){
Get-ADUser -Filter { displayName -match $_} -Properties EmailAddress, Manager | Select Givenname, Surname, SamAccountName, EmailAddress, Manager}
else {Get-ADUser -Filter { displayName -like "AD Test"} -Properties EmailAddress, Manager | Select Givenname, Surname, SamAccountName, EmailAddress, Manager}
} | Export-Csv -Path C:\result.csv
This works fine, but only if users have no middle names ex. John Moore
If the user has a middle name, it doesn't pick it up.
How can I change the script so it picks up users with middle names ex. John Roger Moore?
As Mathias R. Jessen already commented, you can use the -Filter on property DisplayName directly.
The Filter should be a string, not a scriptblock.
Using -Filter also has the advantage that you can suppress exceptions being thrown, so I would build in a step to confirm that we indeed did find a user with that displayname:
Get-Content "C:\displaynames.txt" | ForEach-Object {
$user = Get-ADUSer -Filter "DisplayName -eq '$_'" -Properties DisplayName, EmailAddress, Manager -ErrorAction SilentlyContinue
if ($user) {
# output the wanted properties as **object**
$user | Select-Object Givenname, Surname, SamAccountName, EmailAddress, Manager
}
else {
# nobody in this domain with a displayname like that..
Write-Warning "User '$_' could not be found.."
}
} | Export-Csv -Path 'C:\result.csv' -NoTypeInformation
Note that the Manager property is in the form of the managers DistinguishedName. If you want to get other properties for the manager, like his/her name, you will have to use Get-ADUser -Identity $user.Manager to get the wanted property there too
The basic question here is how to account for middle names.
PowerShell 5 has some AI-powered cmdlets.
Here, I will quote an example from the documentation.
Example 2: Simplify format of a string
$composers = #("Johann Sebastian Bach", "Wolfgang Amadeus Mozart", "Frederic Francois Chopin", "Johannes Brahms")
$composers | Convert-String -Example "first middle last=last, first"
Bach, Johann
Mozart, Wolfgang
Chopin, Frederic
Brahms, Johannes
The first command creates an array that contains first, middle and last names. Note that the last entry has no middle name.
The second command formats the names according to the example. It puts the last name first in the output, followed by the first name. All middle names removed; entry without middle name is handled correctly.
Convert-String (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs

get samaccountname from first and last name

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.

How to get more data from Get-ADuser with powershell

Import-Module ActiveDirectory
Get-ADUser -SearchBase "OU=CompanySite,DC=example,DC=domain,DC=com" -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties "SamAccountName","msDS-UserPasswordExpiryTimeComputed", "Department", "Title", "Manager" |
Select-Object -Property "SamAccountName", #{Name="Password Expiry Date"; Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}; #{Label="Manager";Expression={(Get-aduser -filter {sAMAccountName -eq $_.Manager}.sAMAaccountName)}};# |
Export-Csv "C:\Update\PasswordExpired.csv" -NoTypeInformation
I am trying to get an CSV that contains the employees whose password is expiring and get their managers name, the employees job title, the employees name and the date the password will expire.
However when I run this, I am getting the employees name and date the password is expiring. No other fields. I dont understand where I went wrong
Ok, there were a few errors causing issues:
You had a semi-colon (;) after the Password Expiry Date property in the Select-object portion. This caused the code to terminate at that point. It should be a comma.
For the Manager property, your expression is incorrect. You have your end parentheses after SamAccountName. It should be before the period. Additionally you are trying to match the DN with the SamAccountName data so it will return nothing. Just do a Get-ADUser and set the identity as the $_.Manager output. From there you can use the parentheses to output whatever metadata you want from the full ADUser Object for the manager. You can swap out SamAccountName to DisplayName or something else.
Your code: (Get-ADUser -filter {SamAccountName-eq $_.Manager}.SamAccountName)
Correct code: (Get-ADUser $_.Manager).SamAccountName
Title and Name are not included because you aren't calling them in the Select-object code. The "-Properties" section of Get-ADUser only adds the attribute to the list of retrieved attributes. What you set in Select is what is output to the screen or file.
You had a comment (#) tag before the Export-CSV section so that wasn't running either.
Here's the code. I don't have the manager attribute in my AD so I wasn't able to validate that section, but the rest ran correctly. I've also made it a bit more transportable. The SearchBase is now specified in a variable, as is the export location for the file. Additionally, you don't need to specify SamAccountName in the -Properties section as this is a default attribute for Get-ADUser.
Import-Module ActiveDirectory
$SearchPath = "OU=CompanySite,DC=example,DC=domain,DC=com"
$ExportPath = 'C:\Update\PasswordExpired.csv'
$Users = Get-ADUser -SearchBase $SearchPath -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties "msDS-UserPasswordExpiryTimeComputed", "Department", "Title", "Manager"
$Users | Select-Object -Property Name,"SamAccountName",Title,#{Name="Password Expiry Date"; Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}},#{Label="Manager";Expression={(Get-ADUser $_.Manager).sAMaccountName}} | Export-Csv $ExportPath -NoTypeInformation

Cannot make a search in AD by computer mask

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.