This PowerShell example finds user accounts with the same non-empty User Principal Name (UPN) in an Active Directory forest and exports the matching accounts to CSV. A matching UPN is a review finding, not proof that the accounts are duplicates or safe to merge.
Requirements
Run the script on a Windows computer with the ActiveDirectory PowerShell module and read access to the forest. Set $globalCatalog to a reachable Global Catalog server using port 3268, for example gc01.contoso.com:3268. The query is read-only and writes its report to the current user’s temporary folder.
Find and export repeated UPNs
$globalCatalog = "gc01.contoso.com:3268" # Replace with a GC in your forest
$outputFile = Join-Path $env:TEMP "Duplicate-UPNs-$(Get-Date -Format 'yyyyMMdd-HHmmss').csv"
$users = Get-ADUser -Filter * -Server $globalCatalog -Properties UserPrincipalName, SamAccountName
$duplicates = $users |
Where-Object { -not [string]::IsNullOrWhiteSpace($_.UserPrincipalName) } |
Group-Object -Property UserPrincipalName |
Where-Object { $_.Count -gt 1 } |
ForEach-Object {
$_.Group | Select-Object UserPrincipalName, Name, SamAccountName, DistinguishedName
}
if ($duplicates) {
$duplicates | Sort-Object UserPrincipalName, DistinguishedName |
Export-Csv -Path $outputFile -NoTypeInformation
Write-Host "Exported matching accounts to $outputFile"
}
else {
Write-Host "No repeated non-empty UPNs were found in this query."
}
The Global Catalog endpoint lets the query search across domains in the forest. Results depend on the chosen catalog being reachable and current. Review each result with the relevant directory administrators before changing an account; do not delete, rename, or merge accounts solely because their UPNs match.
See Microsoft’s Get-ADUser documentation and its guide to specifying a Global Catalog server and port for details.