Reputation: 49
I'm writing a powershell script that will search active directory and give me info on users like this:
$fname = Read-Host 'Enter first name'
$lname = Read-Host 'Enter Last Name'
$search = [adsisearcher]"(&(ObjectCategory=Person)(ObjectClass=User)(givenName=$fname)(sn=$lname))"
$users = $search.FindAll()
foreach($user in $users) {
$displayname = $user.Properties['displayname']
"$displayname"
}
That will return a list of users who have the same first and last names:
User1
User2
User3
User4
I'd then like to be able to select which user I want to show further info on, something like this:
Read-Host 'Enter user number'
#input 1 - 4
#returns exchange server name for the selected user:
$msExchHomeServerName = $user.Properties['msExchHomeServerName']
"Exchange server: $msExchHomeServerName"
I can't figure out how to return a selectable list that lets me get further details on that user.
Upvotes: 0
Views: 842
Reputation: 1190
If you want to avoid user selection error, you can use the PromptForChoice
method :
$fname = (Read-Host 'Enter first name').Trim()
$lname = (Read-Host 'Enter Last Name').Trim()
$filter = "(&(samAccountType=805306368)(givenName=$fname)(sn=$lname))"
$propsToLoad = @('displayname','samaccountname', 'mail', 'l', 'department', 'msExchHomeServerName')
$search = [System.DirectoryServices.DirectorySearcher]::new($filter, $propsToLoad)
$results=$search.FindAll()
$results[$Host.UI.PromptForChoice( "Choose the namesake you want to see",`
"Type the corresponding SamAccountName", ($results | ForEach-Object `
{ New-Object System.Management.Automation.Host.ChoiceDescription( `
$_.Properties.samaccountname, $_.Properties.department) }), 0)].Properties.Values
This shows you this once you have typed givenName and surName :
Enter first name: Justine
Enter Last Name: Noix
Choose the namesake you want to see
Type the corresponding SamAccountName
[] JNoix [] JuNoix [?] Aide (la valeur par défaut est « JNoix ») : junoix
JuNoix
Justine Noix
LDAP://CN=Justine Noix,OU=R&D,OU=Tests,DC=someDomain,DC=adds
[email protected]
R&D
SomeCity
mailserver.someDomain.adds
if you type a wrong samAccountName, it re-asks again.
if you don't care about any help or have no department setted in AD, simply replace the last line by :
$results[$Host.UI.PromptForChoice( "Choose the namesake you want to see",`
"Type the corresponding SamAccountName", ($results | ForEach-Object `
{ New-Object System.Management.Automation.Host.ChoiceDescription( `
$_.Properties.samaccountname, "") }), 0)].Properties.Values
Upvotes: 0
Reputation: 909
You have to specify the properties that you'd like to load for each user. [adsisearcher]
is a type accelerator for DirectorySearcher
, so try this:
$filter = "(&(ObjectCategory=Person)(ObjectClass=User)(givenName=$fname)(sn=$lname))"
$propsToLoad = @('displayname', 'msExchHomeServerName')
$search = [System.DirectoryServices.DirectorySearcher]::new($filter, $propsToLoad)
Upvotes: 0
Reputation: 1258
This works for me. I'm more familiar with PSCustomObjects, but you could do this as a hashtable instead, I'm sure (although I think hashtables get funny if you try and use an integer as a key).
And I'm sorry, I'm too lazy to refactor this with ADSI, but hopefully the logic is clear.
If you wanted to, you could return the user properties you might need with your initial LDAP query and add them to the [PSCustomObject]
you're creating for each user. Then just pull the properties out of $usertable
rather than doing another AD query. (See the second example.)
However, I'm really adamant that if it's more than a few properties for more than a few users, don't try and grab everything at once. I get really sick of lazy LDAP filters with -properties *
when you only want one property. In my environment, if I get all the properties on just my account, it's 74 KB. That starts to add up quickly when dragging stuff out of LDAP.
# sort user list by desired attribute below e.g. samaccountname, lastname, etc
$users = get-aduser -filter 'name -like "macdo*"' | sort samaccountname
# create an array to store the user results
$usertable = @()
$no = 0
$users | foreach {
$no++
$o = [PSCustomObject]@{
No = $no
Name = $_.samaccountname
}
$usertable += $o
}
$usertable |sort no
# this is what the table will look like on screen
No Name
-- ----
1 AKMacDonald
2 AMacDonald
3 BMacDonald
4 BMacdonnell
$myint = Read-Host 'Enter user number'
> Enter user number: 29
# Select desired user properties in Get-ADUser below
$ADuser = $usertable | where {$_.no -eq $myin} |select -ExpandProperty Name |
Get-Aduser -Properties msExchHomeServerName
$ADuser
#AD user output
DistinguishedName : CN=BMacDonald,OU=Accounts,DC=example,DC=com
Enabled : False
GivenName : Bruce
Name : BMacDonald
...
If you're grabbing a few extra attributes with your initial AD query, you can store them in the $usertable
for quick retrieval.
# grab msExchHomeServerName in this query
$users = get-aduser -filter 'name -like "macdo*"' -properties msExchHomeServerName |
sort samaccountname
# create an array to store the user results
$usertable = @()
$no = 0
$users | foreach {
$no++
$o = [PSCustomObject]@{
No = $no
Name = $_.samaccountname
Exchsrv= $_.msExchHomeServerName
}
$usertable += $o
}
# do a "select" below if you don't want to display everything in $usertable
$usertable |sort no
# $usertable contents
No Name Exchsrv
-- ---- ----
1 AKMacDonald Exch1
2 AMacDonald Exch1
3 BMacDonald Exch2
4 BMacdonnell Exch3
$myint = Read-Host 'Enter user number'
> Enter user number: 29
# Select desired user properties from $usertable
$usertable | where {$_.no -eq $myint} | Select Name,Exchsrv
# output
Name Exchsrv
---- ----
AKMacDonald Exch1
Upvotes: 0