加速PowerShell脚本:批量基于SamAccountName查询经理信息优化
Hey Sarah, totally get the frustration of waiting around for a script to plow through 1400+ user entries—let’s cut that runtime down dramatically! Here are the most impactful tweaks you can make, focused on reducing redundant AD calls and optimizing how you handle data:
1. Batch AD Queries (Biggest Performance Win)
The #1 slowdown here is almost certainly querying Active Directory one user at a time. Instead, load all your SamAccountNames first, then fetch all those users in a single AD call. Even better, cache manager details so you don’t re-query the same manager 100 times if multiple users report to them.
Here’s a revised snippet implementing this:
# Load all SamAccountNames from your text file $samAccounts = Get-Content "C:\path\to\your\subordinates.txt" # Fetch ALL target users in ONE query—only request properties you actually need $users = Get-ADUser -Filter { SamAccountName -in $samAccounts } -Properties Manager, EmployeeID, Name # Create a cache to store already-fetched managers (avoids duplicate AD calls) $managerCache = @{} # Process each user to get manager details $results = foreach ($user in $users) { if ($user.Manager) { # Check cache first—only query AD if we haven't seen this manager yet if (-not $managerCache.ContainsKey($user.Manager)) { $managerCache[$user.Manager] = Get-ADUser -Identity $user.Manager -Properties EmployeeID, Name } $manager = $managerCache[$user.Manager] [PSCustomObject]@{ EmployeeName = $user.Name EmployeeID = $user.EmployeeID ManagerName = $manager.Name ManagerID = $manager.EmployeeID } } else { # Handle users with no assigned manager [PSCustomObject]@{ EmployeeName = $user.Name EmployeeID = $user.EmployeeID ManagerName = "No manager assigned" ManagerID = $null } } } # Export all results in one go (avoids repeated file I/O) $results | Export-Csv "C:\path\to\manager_results.csv" -NoTypeInformation
2. Optimize File I/O
- Load files in bulk: Using
Get-Content(or[System.IO.File]::ReadAllLines()) loads the entire text file into memory at once, which is way faster than processing line-by-line for small-to-medium files like yours. - Avoid incremental exports: Collect all results in an array first, then export everything with a single
Export-Csvcall. Using-Appendin a loop forces the script to open/close the file hundreds of times, which adds unnecessary overhead.
3. Request Only Necessary AD Properties
Never use -Properties * unless you truly need every attribute from AD. Specify exactly the properties you need (like Manager, EmployeeID, Name) in your Get-ADUser calls—this reduces the amount of data transferred from AD and speeds up processing.
4. Optional: Parallel Processing (PowerShell 7+)
If you’re running PowerShell 7 or later, you can use parallel processing to handle multiple users at once. Just be careful not to overload your domain controllers—use -ThrottleLimit to cap concurrent queries:
# Use a thread-safe cache for parallel processing $managerCache = [System.Collections.Concurrent.ConcurrentDictionary[string, PSObject]]::new() $results = $users | ForEach-Object -Parallel { $user = $_ $cache = $using:managerCache if ($user.Manager) { if (-not $cache.ContainsKey($user.Manager)) { $manager = Get-ADUser -Identity $user.Manager -Properties EmployeeID, Name $cache.TryAdd($user.Manager, $manager) | Out-Null } $manager = $cache[$user.Manager] [PSCustomObject]@{ EmployeeName = $user.Name EmployeeID = $user.EmployeeID ManagerName = $manager.Name ManagerID = $manager.EmployeeID } } else { [PSCustomObject]@{ EmployeeName = $user.Name EmployeeID = $user.EmployeeID ManagerName = "No manager assigned" ManagerID = $null } } } -ThrottleLimit 10 # Adjust based on your AD server's capacity
These changes should slash your script’s runtime—especially the batch query and manager cache, which will reduce your AD calls from 1400+ to just a handful (one for all users, plus one per unique manager).
内容的提问来源于stack exchange,提问作者Sarah

