Gather user information

Our AD contains over 20,000 users and I want to create a script to help our service desk gather basic details about the caller.

My goal is to offer the agent a script to search AD based on Name and Given Name with some wildcards. Then display a list of marches. Then the agent will “select” one match and the script would output user details such as full name, SAMACCOUNT NAME, UserPrincipalName,… group membership.
to an out-grid.

I’m able to handle the start and end of the script, but I’m having issues creating a dynamic menu.

Could someone offer some guidance?

Welcome to the forum. :wave:t4:

Have you thought about using …

… for that purpose?

With the parameter -OutputMode you can set if it’s possible to select one or more elements of the list. :wink: :+1:t4:

1 Like

Thank you very much for that hint, I was able to figure out a way to leverage out-grid to select the correct account and then display the desired fields.

I’m still working on it, but here is a copy of my code. Please be gentile

#Get-Module -ListAvailable
#Collect Name(s) from consule

$targets = @()
$inputGivenName = @()
$inputsurname = @()
$target = @()
$suspects =@()
$suspect =@()

#gather name info

$inputGivenName = Read-Host “Given Name (aul or Pau are valid)”
$inputsurname = Read-Host “Last name (mith or Smit are valid)”

type or paste code here

#Find user and pipe to outgrid

$targets += Get-ADUser -Filter “givenname -like ‘$inputGivenName’ -and surname -like ‘$inputsurname’” -Properties *
#$suspects = $targets | Select-Object -Property Name,GivenName,SamAccountName #
$target= $targets | Select-Object -Property Name,GivenName,SamAccountName,UserPrincipalName | Out-GridView -PassThru | Select-Object SamAccountName

#convert $target
$TMP = $target.SamAccountName

$suspect = Get-ADUser $tmp -properties *

#output user object details

Write-Host “____”
write-host "Name: " $suspect.Name
write-host "Given Name: " $suspect.GivenName
write-host "Display Name "$suspect.DisplayName
Write-Host "Locket Out: " $suspect.LockedOut
write-host "Sam Account Name: " $suspect.SamAccountName
write-host "UPN: " $suspect.UserPrincipalName
write-host "BadLogonCount: " $suspect.BadLogonCount
write-host "Employee ID: " $suspect.EmployeeID
write-host "Department: " $suspect.Department
write-host "Description: "$suspect.Description
write-host "DistinguishedName: " $suspect.DistinguishedName
write-host "HomeDirectory: " $suspect.HomeDirectory
write-host "Manager: "$suspect.Manager

#Gather Groups

$groups = Get-ADPrincipalGroupMembership $suspect.SamAccountName
Write-Host “____”
Write-Host “Group Memberships”

foreach ( $i in $groups) {

Write-Host $  


While your code may do what you need it is quite inefficient and cumbersome.

You should not use “*” for the -Properties parameter for your Get-ADUser query as this slows your query down quite a lot. You should always only query the least amount of data from your AD as possible. … and never more attributes than needed. I’d recommend as well to use a -SearchBase for your query.

Next - you query your AD twice - that’s unnecessary and time consuming. Instead you should use the data you already queried for the final output of the selected user.

With the parameter -OutputMode Single for Out-GridView you can control if the user is able to select only one element or more.

The extended use of Write-Host is considered bad style and should be avoided. … and it is unnecessary in the vast majority of the cases. :wink:

Something like this could be a good starting point:

$InputGivenName = Read-Host "Given Name (*aul or Pau* are valid)"
$InputSurname = Read-Host "Last name (*mith or Smit* are valid)" 

$Searchbase = 'OU=Users,OU=Berlin,OU=Germany,OU=Europe,DC=contoso,DC=de'

$ADUserProperties = 

$QueryResultList = 
    Get-ADUser -Filter "givenname -like '$InputGivenName' -and surname -like '$InputSurname'" -Properties $ADUserProperties -SearchBase $Searchbase
$SelectedUser = 
    $QueryResultList | 
        Select-Object -Property Name, GivenName, SamAccountName, UserPrincipalName | 
            Out-GridView -OutputMode Single

"`nSelected User:`n-------------"
$QueryResultList |
    Where-Object -Property sAMAccountName -EQ -Value $SelectedUser.sAMAccountName |
        Select-Object -Property $ADUserProperties

$GroupMembershipList = 
    Get-ADPrincipalGroupMembership $SelectedUser.SamAccountName

"`nGroup Memberships`n-----------------"

inefficient and cumbersome, I’ve been called worse!

I will take your notes and try to improve the code… Thank you

Not you - your code! :wink: … and who says you couldn’t improve? … yourself and your code!! :wink: :+1:t4: :love_you_gesture:t4:

1 Like

Your script is a huge improvement, thank you for sharing and guiding me here. I’m taking notes…

But the $QueryResultList variable contains all the properties defined VIA $ADUserProperties. But $SelectedUser does not contain the same properties. It only contains the properties defined in the select-object statement before out-gridView

Here is the get-member output of $QueryResultList and $SelectedUser.

This is why I was reading AD twice… the properties I want to display don’t survive the Out-GridView instructions.

PS H:\Dev> $QueryResultList | gm

TypeName: Deserialized.Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition

GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, System.IFormatProvider format…
PSComputerName NoteProperty string PSComputerName=localhost
PSShowComputerName NoteProperty bool PSShowComputerName=False
RunspaceId NoteProperty guid RunspaceId=5b7ee0e5-22eb-4cb5-bbfb-cc59048d0a2d
AccountExpirationDate Property {get;set;}
accountExpires Property System.Int64 {get;set;}
AccountLockoutTime Property {get;set;}
AccountNotDelegated Property System.Boolean {get;set;}
AllowReversiblePasswordEncryption Property System.Boolean {get;set;}
AuthenticationPolicy Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
AuthenticationPolicySilo Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
BadLogonCount Property System.Int32 {get;set;}
badPasswordTime Property System.Int64 {get;set;}
badPwdCount Property System.Int32 {get;set;}
businessCategory Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
CannotChangePassword Property System.Boolean {get;set;}
CanonicalName Property System.String {get;set;}
Certificates Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
chicagoID Property System.String {get;set;}
City Property {get;set;}
CN Property System.String {get;set;}
codePage Property System.Int32 {get;set;}
Company Property System.String {get;set;}
CompoundIdentitySupported Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
Country Property {get;set;}
countryCode Property System.Int32 {get;set;}
Created Property System.DateTime {get;set;}
createTimeStamp Property System.DateTime {get;set;}
Deleted Property {get;set;}
Department Property System.String {get;set;}
Description Property System.String {get;set;}
DisplayName Property System.String {get;set;}
DistinguishedName Property System.String {get;set;}
Division Property System.String {get;set;}
DoesNotRequirePreAuth Property System.Boolean {get;set;}
dSCorePropagationData Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
EmailAddress Property System.String {get;set;}
EmployeeID Property System.String {get;set;}
EmployeeNumber Property {get;set;}
employeeType Property System.String {get;set;}
Enabled Property System.Boolean {get;set;}
extensionAttribute13 Property System.String {get;set;}
extensionAttribute2 Property System.String {get;set;}
Fax Property {get;set;}
GivenName Property System.String {get;set;}
HomeDirectory Property System.String {get;set;}
HomedirRequired Property System.Boolean {get;set;}
HomeDrive Property System.String {get;set;}
homeMDB Property System.String {get;set;}
homeMTA Property System.String {get;set;}
HomePage Property {get;set;}
HomePhone Property {get;set;}
info Property System.String {get;set;}
Initials Property {get;set;}
instanceType Property System.Int32 {get;set;}
isDeleted Property {get;set;}
KerberosEncryptionType Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
LastBadPasswordAttempt Property System.DateTime {get;set;}
LastKnownParent Property {get;set;}
lastLogoff Property System.Int64 {get;set;}
lastLogon Property System.Int64 {get;set;}
LastLogonDate Property System.DateTime {get;set;}
lastLogonTimestamp Property System.Int64 {get;set;}
legacyExchangeDN Property System.String {get;set;}
LockedOut Property System.Boolean {get;set;}
logonCount Property System.Int32 {get;set;}
LogonWorkstations Property {get;set;}
mail Property System.String {get;set;}
mailNickname Property System.String {get;set;}
Manager Property {get;set;}
mDBUseDefaults Property System.Boolean {get;set;}
MemberOf Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
MNSLogonAccount Property System.Boolean {get;set;}
MobilePhone Property {get;set;}
Modified Property System.DateTime {get;set;}
modifyTimeStamp Property System.DateTime {get;set;}
msDS-User-Account-Control-Computed Property System.Int32 {get;set;}
msExchBlockedSendersHash Property System.Byte {get;set;}
msExchHideFromAddressLists Property System.Boolean {get;set;}
msExchHomeServerName Property System.String {get;set;}
msExchMailboxGuid Property System.Byte {get;set;}
msExchMailboxSecurityDescriptor Property System.String {get;set;}
msExchOmaAdminWirelessEnable Property System.Int32 {get;set;}
msExchPoliciesIncluded Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
msExchRBACPolicyLink Property System.String {get;set;}
msExchRecipientDisplayType Property System.Int32 {get;set;}
msExchRecipientTypeDetails Property System.Int64 {get;set;}
msExchTextMessagingState Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
msExchUMDtmfMap Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
msExchUserAccountControl Property System.Int32 {get;set;}
msExchUserCulture Property System.String {get;set;}
msExchVersion Property System.Int64 {get;set;}
msExchWhenMailboxCreated Property System.DateTime {get;set;}
msTSExpireDate Property System.DateTime {get;set;}
msTSLicenseVersion Property System.String {get;set;}
msTSLicenseVersion2 Property System.String {get;set;}
msTSLicenseVersion3 Property System.String {get;set;}
msTSManagingLS Property System.String {get;set;}
Name Property System.String {get;set;}
nTSecurityDescriptor Property System.String {get;set;}
ObjectCategory Property System.String {get;set;}
ObjectClass Property System.String {get;set;}
ObjectGUID Property System.Guid {get;set;}
objectSid Property System.String {get;set;}
Office Property {get;set;}
OfficePhone Property System.String {get;set;}
Organization Property {get;set;}
OtherName Property {get;set;}
PasswordExpired Property System.Boolean {get;set;}
PasswordLastSet Property System.DateTime {get;set;}
PasswordNeverExpires Property System.Boolean {get;set;}
PasswordNotRequired Property System.Boolean {get;set;}
personalTitle Property System.String {get;set;}
POBox Property {get;set;}
PostalCode Property {get;set;}
PrimaryGroup Property System.String {get;set;}
primaryGroupID Property System.Int32 {get;set;}
PrincipalsAllowedToDelegateToAccount Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
ProfilePath Property {get;set;}
ProtectedFromAccidentalDeletion Property System.Boolean {get;set;}
proxyAddresses Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
pwdLastSet Property System.Int64 {get;set;}
SamAccountName Property System.String {get;set;}
sAMAccountType Property System.Int32 {get;set;}
ScriptPath Property System.String {get;set;}
sDRightsEffective Property System.Int32 {get;set;}
ServicePrincipalNames Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
SID Property System.String {get;set;}
SIDHistory Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
SmartcardLogonRequired Property System.Boolean {get;set;}
sn Property System.String {get;set;}
State Property {get;set;}
StreetAddress Property {get;set;}
Surname Property System.String {get;set;}
telephoneNumber Property System.String {get;set;}
thumbnailPhoto Property System.Byte {get;set;}
Title Property System.String {get;set;}
TrustedForDelegation Property System.Boolean {get;set;}
TrustedToAuthForDelegation Property System.Boolean {get;set;}
UseDESKeyOnly Property System.Boolean {get;set;}
userAccountControl Property System.Int32 {get;set;}
userCertificate Property Deserialized.Microsoft.ActiveDirectory.Management.ADPropertyValueCollection {ge…
UserPrincipalName Property System.String {get;set;}
uSNChanged Property System.Int64 {get;set;}
uSNCreated Property System.Int64 {get;set;}
whenChanged Property System.DateTime {get;set;}
whenCreated Property System.DateTime {get;set;}


PS H:\Dev> $SelectedUser | GM

TypeName: Selected.System.Management.Automation.PSCustomObject

Name MemberType Definition

Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
GivenName NoteProperty string GivenName=Daniel
Name NoteProperty string Name=Daniel Houle
SamAccountName NoteProperty string SamAccountName=www6329
UserPrincipalName NoteProperty string UserPrincipalName=www6329@UCHAD.UCHOSPITALS.EDU

Thank you

You’re perfectly right … ooops … :wink:

I corrected my code suggestion above … try now.

They don’t have to. We just need to use the selected user as filter for the already collected data.

But the outut of this looks like you’re still querying with -Properties * … I’d recommend to change that. Depending on your AD it slows your query and puts al lot more stress on to your AD for the query.

Thank you for that correction.

This script is to be used on an Ad Hoc bases to collect user details for service tickets. I’m not concerned by the load… it will be used 20 times per day max…

Thank you

At the end of the day it stays your decision of course … but because it’s actually no effort you could add this little optimization anyway … it won’t hurt you but it will actually improve your script. :wink: