Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| -Username | [string] | Yes · Pipeline | Identity to search for. Accepts SamAccountName, UPN, email address, display name, DistinguishedName, or CanonicalName. |
| -DomainController | [string] | Optional | Override the auto-resolved DC. Useful for targeting a specific server during troubleshooting or replication verification. |
| -GlobalCatalog | [string] | Optional | Override the Global Catalog used for the initial forest-wide lookup. Auto-discovered in the current AD site if omitted. Append :3268 or let the function add the port automatically. |
| -PreferredSite | [string] | Optional | Prefer a DC in this AD site when resolving the target domain controller. Falls back to any available writable DC if no DC exists in the specified site for the resolved domain. |
| -Properties | [Array] | Optional | Bypasses the standard output object and returns a raw AD attribute selection via Select-Object. Useful for targeted attribute inspection or flexible pipeline use. |
How It Works
msDS-ResultantPSO, all extensionAttributes, replication metadata).
Get-ADReplicationAttributeMetadata is called against userAccountControl to surface LastStatusChangeDate and LastStatusChangeValue — allowing you to see exactly when an account was enabled or disabled, and which DC originated that change.
Output — PSCustomObject
Examples
Get-MyUser -Username "jdoe"
Auto-discovers a GC, resolves the domain, queries the correct DC, and returns the full standardised output object.
"jdoe", "asmith", "john.doe@child2.corp.local" | Get-MyUser
Each identity is resolved independently. Mixed formats (SamAccountName, UPN, email) are all accepted in the same pipeline.
Get-MyUser -Username "john.doe@child2.corp.local" -PreferredSite "Doha-Site"
Pins DC resolution to the Doha-Site AD site. Falls back to any writable DC in child2.corp.local if the site has none.
Get-MyUser -Username "jdoe" -Properties DisplayName, Department, Title, extensionAttribute1
When -Properties is supplied the standard output object is bypassed entirely. The raw ADUser object is returned via Select-Object — useful for one-off attribute checks or feeding into other cmdlets.
Get-MyUser -Username "jdoe" | Select-Object -ExpandProperty SamAccountName | Test-MyUserStatus -SkipCredentialTest
The two functions compose naturally via the pipeline. Get-MyUser resolves the identity; Test-MyUserStatus performs the health evaluation.
Full Source
function Get-MyUser { [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] [string]$Username, [Parameter(Mandatory = $false)] [string]$DomainController, [Parameter(Mandatory = $false)] [string]$GlobalCatalog, [Parameter(Mandatory = $false)] [string]$PreferredSite, [Parameter(Mandatory = $false)] [Array]$Properties ) Begin {} Process { # ── Step 1: Resolve the correct DC for this identity ───────────────────────── $resolveParams = @{ Identity = $Username } if ($GlobalCatalog) { $resolveParams['GlobalCatalog'] = $GlobalCatalog } if ($PreferredSite) { $resolveParams['PreferredSite'] = $PreferredSite } try { $resolved = Get-ADTargetServer @resolveParams -ErrorAction Stop } catch { Write-Error "Could not resolve a target server for '$Username'. $_" return } if (-not $resolved) { Write-Warning "No user found for '$Username'." return } $targetServer = if ($DomainController) { $DomainController } else { $resolved.DomainController } # ── Step 2: Full attribute retrieval from the resolved domain's DC ─────────── # GC holds a partial attribute set only. Full DC query is required for # msDS-ResultantPSO, all extensionAttributes, and replication metadata. try { $User = Get-ADUser -Identity $resolved.SamAccountName ` -Properties *, "msDS-UserPasswordExpiryTimeComputed", "msDS-ResultantPSO" ` -Server $targetServer ` -ErrorAction Stop } catch { Write-Error "Failed to retrieve full AD user object for '$($resolved.SamAccountName)' from '$targetServer'. $_" return } # ── Step 3: Replication metadata for account status change tracking ────────── try { $Metadata = Get-ADReplicationAttributeMetadata ` -Object $User.DistinguishedName ` -Server $targetServer ` -ErrorAction Stop | Where-Object { $_.AttributeName -eq "userAccountControl" } } catch { Write-Warning "Could not retrieve replication metadata for '$($User.DistinguishedName)'. LastStatusChangeDate will be null." $Metadata = $null } # ── Step 4: Output ──────────────────────────────────────────────────────────── if ($Properties) { return $User | Select-Object $Properties } [PSCustomObject]@{ Name = $User.Name UserPrincipalName = $User.UserPrincipalName SamAccountName = $User.SamAccountName DisplayName = $User.DisplayName EmailAddress = $User.EmailAddress Department = $User.Department Title = $User.Title ExtensionAttribute2 = $User.extensionAttribute2 Description = $User.Description FGPPolicy = if ($User.'msDS-ResultantPSO') { ($User.'msDS-ResultantPSO' -split ',')[0] -replace '^CN=', '' } else { $null } Manager = if ($User.Manager) { ($User.Manager -split ',')[0] -replace '^CN=', '' } else { $null } Enabled = $User.Enabled LockedOut = $User.LockedOut LockoutTime = $User.LockoutTime AccountLockoutTime = $User.AccountLockoutTime PasswordExpired = $User.PasswordExpired PasswordNeverExpires = $User.PasswordNeverExpires CannotChangePassword = $User.CannotChangePassword PasswordLastSet = $User.PasswordLastSet AccountExpirationDate = $User.AccountExpirationDate LastLogonDate = $User.LastLogonDate WhenCreated = $User.WhenCreated DistinguishedName = $User.DistinguishedName Domain = $resolved.Domain ResolvedDC = $targetServer msExchRecipientDisplayType = $User.msExchRecipientDisplayType LastStatusChangeDate = $Metadata.LastOriginatingChangeTime LastStatusChangeValue = $Metadata.AttributeValue } } End {} }