PowerShell ForEach循环重复迭代两次问题求助
Let's break down why most of your computer accounts are being processed twice—this is almost always tied to overlapping search scopes or duplicate results from Search-ADAccount. Here's how to diagnose and fix it:
1. Check for Overlapping OUs in $OUs
The most common culprit here is that your $OUs array contains parent OUs and their child OUs. Since Search-ADAccount defaults to a Subtree search scope (it recursively looks through all child OUs), an account in a child OU will be picked up once by the child OU search and once by the parent OU search.
To verify this, add a debug line to print the OU being processed:
foreach ($OU in $OUs) { Write-Host "=== Processing OU: $($OU.DistinguishedName) ===" # Rest of your code... }
If you see a parent OU followed by its child OU in the output, that's the source of duplicates. Fix this by either:
- Removing parent OUs from
$OUsif you only need to target specific child OUs - Adding
-SearchScope OneLevelto your$scopesplatting to only search the current OU (not child OUs)
2. Deduplicate Search-ADAccount Results
Even if your OUs are clean, AD can sometimes return duplicate objects (rare, but possible with replication quirks). Add a deduplication step using the unique DistinguishedName property (every AD object has a unique DN):
$accounts = Search-ADAccount -SearchBase $OU.DistinguishedName -AccountInactive -TimeSpan ([timespan]'7D') @scope | Select-Object -Unique DistinguishedName, Name, ObjectClass | ForEach-Object { Get-ADObject -Identity $_.DistinguishedName }
This ensures only unique accounts make it to your inner loop.
3. Fix the Redundant $days Line
I noticed this line in your code:
$days = $days + "D"
This is unnecessary (you're hardcoding [timespan]7D anyway) and will break if you run the loop multiple times (it turns 7D into 7DD, which is invalid for a timespan). Delete this line entirely to avoid future errors.
4. Debug Account Counts per OU
Add a line to print how many accounts are found in each OU—this will help you confirm if duplicates are coming from specific OUs:
$accounts = Search-ADAccount -SearchBase $OU.DistinguishedName -AccountInactive -TimeSpan ([timespan]'7D') @scope | Select-Object -Unique DistinguishedName, Name Write-Host "Found $($accounts.Count) unique accounts in this OU"
Fixed Example Code
Here's your code with all the fixes applied:
# Define your scope (add -SearchScope OneLevel if you don't want child OUs) $scope = @{ # Optional: SearchScope = 'OneLevel' } foreach ($OU in $OUs) { Write-Host "=== Processing OU: $($OU.DistinguishedName) ===" # Get unique inactive accounts $accounts = Search-ADAccount -SearchBase $OU.DistinguishedName -AccountInactive -TimeSpan ([timespan]'7D') @scope | Select-Object -Unique DistinguishedName, Name Write-Host "Found $($accounts.Count) unique accounts to process" foreach($account in $accounts){ If ($noDisable -notcontains $account.Name) { Write-Host "Processing account: $($account.Name) ($($account.DistinguishedName))" # Uncomment once you've verified no duplicates # Disable-ADAccount -Identity $account.DistinguishedName -Verbose -WhatIf # $account | Select-Object Name, DistinguishedName | Export-Csv $logFile -Append -NoTypeInformation } } }
The core issue is almost certainly overlapping OU search ranges. Once you fix that or add deduplication, your accounts will only be processed once.
内容的提问来源于stack exchange,提问作者poisedforflight

