Created
June 25, 2025 14:59
-
-
Save win2000b/f6f0e2670e325480a3eae78900f1844b to your computer and use it in GitHub Desktop.
Find Manager Subordinates and recurse down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Run with "powershell -ExecutionPolicy Bypass -File .\Get-EntraSubordinates-WithManagerOnly.ps1" | |
| # Connect to Microsoft Graph | |
| Connect-MgGraph -Scopes "User.Read.All", "Directory.Read.All" | |
| # Function to recursively retrieve all subordinates under a manager | |
| function Get-SubordinatesRecursive { | |
| param ( | |
| [string]$ManagerId, | |
| [hashtable]$Visited, | |
| [string]$ManagerName | |
| ) | |
| $results = @() | |
| if (-not ($ManagerId -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$')) { | |
| Write-Warning "Skipping invalid manager ID: $ManagerId" | |
| return $results | |
| } | |
| if ($Visited.ContainsKey($ManagerId)) { | |
| return $results | |
| } | |
| $Visited[$ManagerId] = $true | |
| try { | |
| $directReports = Get-MgUserDirectReport -UserId $ManagerId -All | |
| } | |
| catch { | |
| Write-Warning ("Error retrieving direct reports for manager ID ${ManagerId}: " + $_.Exception.Message) | |
| return $results | |
| } | |
| foreach ($report in $directReports) { | |
| try { | |
| $user = Get-MgUser -UserId $report.Id | |
| $user | Add-Member -NotePropertyName ManagerName -NotePropertyValue $ManagerName | |
| $results += $user | |
| $childResults = Get-SubordinatesRecursive -ManagerId $user.Id -Visited $Visited -ManagerName $user.DisplayName | |
| $results += $childResults | |
| } | |
| catch { | |
| Write-Warning "Could not retrieve user details for $($report.Id): $_" | |
| } | |
| } | |
| return $results | |
| } | |
| # Prompt for the manager | |
| $managerInput = Read-Host "Enter part or all of the manager's Display Name or UPN" | |
| $allUsers = Get-MgUser -All | Select-Object Id, DisplayName, UserPrincipalName | |
| $matchedManagers = $allUsers | Where-Object { | |
| $_.UserPrincipalName -like "*$managerInput*" -or $_.DisplayName -like "*$managerInput*" | |
| } | |
| if ($matchedManagers.Count -eq 0) { | |
| Write-Error "No matching manager found. Please check the input." | |
| return | |
| } | |
| elseif ($matchedManagers.Count -gt 1) { | |
| Write-Output "Multiple matches found:" | |
| $matchedManagers | ForEach-Object -Begin { $i = 0 } -Process { | |
| "$i`t$($_.DisplayName) ($($_.UserPrincipalName))" | |
| $i++ | |
| } | |
| $selectedIndex = Read-Host "Enter the index number (0 to $($matchedManagers.Count - 1)) for the correct manager" | |
| if (-not ($selectedIndex -match '^\d+$') -or [int]$selectedIndex -ge $matchedManagers.Count) { | |
| Write-Error "Invalid index. Exiting." | |
| return | |
| } | |
| $manager = $matchedManagers[$selectedIndex] | |
| } | |
| else { | |
| $manager = $matchedManagers[0] | |
| } | |
| if (-not $manager.Id) { | |
| Write-Error "Manager ID is null or empty. Exiting." | |
| return | |
| } | |
| Write-Output "Found top-level manager: $($manager.DisplayName) | ID: $($manager.Id)" | |
| Write-Output "Recursively collecting subordinates..." | |
| $visited = @{} | |
| $allSubordinates = Get-SubordinatesRecursive -ManagerId $manager.Id -Visited $visited -ManagerName $manager.DisplayName | |
| Write-Output "Total subordinates found: $($allSubordinates.Count)" | |
| # Output to console | |
| $allSubordinates | Select-Object DisplayName, UserPrincipalName, ManagerName | Format-Table -AutoSize | |
| # Export to CSV | |
| $csvPath = "Subordinates_With_Manager.csv" | |
| $allSubordinates | Select-Object DisplayName, UserPrincipalName, JobTitle, Department, ManagerName | Export-Csv -Path $csvPath -NoTypeInformation | |
| Write-Output "Results exported to: $csvPath" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment