Reputation:
I have had this issue a long time, whenever I presume that it's going to output all data it does not.
Example:
$groups = "group1","Group2","Group3" # to be excluded
foreach ($group in $groups) {
$dns = (Get-ADGroup "$Group").DistinguishedName
}
Write-Host $dns
will output only one group's distinguished name, but if at the same time I output
(Get-ADGroup "$Group").DistinguishedName | Out-File c:\list.txt
I will get all 3. The same goes with `Get-ADUser, if I try to get user from an array.
Any real solution anyone has come accross?
Upvotes: 0
Views: 254
Reputation: 200373
PowerShell doesn't magically create an array just because you will it. Since $dns
isn't an array from the start your code is replacing its value with every iteration, so you end up with just the last value after the loop terminates.
You have 2 ways of fixing this issue:
Define $dns
as an array before the loop, and append to that array inside the loop.
$dns = @()
foreach ($group in $groups) {
$dns += (Get-ADGroup "$Group").DistinguishedName
}
Although virtually everyone seems to be doing it this way, the approach is NOT RECOMMENDED for performance reasons. Appending to an array is expensive, because it essentially creates a new array with increased size, moves all existing elements and puts the new element in the new free slot, then replaces the original array.
Output the results inside the loop and collect the entire loop output in a variable.
$dns = foreach ($group in $groups) {
(Get-ADGroup "$Group").DistinguishedName
}
This approach has significantly better performance than appending inside a loop. However, it's worth noting, that if the loop produces zero or one elements, the result will be either $null
or a simple value, not an array. You can force it to an array by putting the loop in the array construction operator, though:
$dns = @(foreach ($group in $groups) {
(Get-ADGroup "$Group").DistinguishedName
})
Addendum: As @Clijsters mentioned in the comments there's actually a third way to approach this issue, using a .Net collection instead of basic PowerShell arrays:
$dns = New-Object System.Collections.ArrayList
foreach ($group in $groups) {
$dns.Add((Get-ADGroup "$Group").DistinguishedName) | Out-Null
}
Appending to a collection is far less expensive than appending to a PowerShell array. However, there's some overhead to instantiating the collection. You'll get the best performance by simply collecting loop output in a variable ($dns = foreach (...) {...}
).
Upvotes: 2
Reputation: 17171
The problem is your Write-Host
is outside of your loop!
$groups = "Group1", "Group2", "Group3"
foreach ($group in $groups) {
$dns = (Get-ADGroup $group).DistinguishedName
Write-Host $dns # <--- it's inside, now!
}
This will write the value out for each group, not just the last one.
Upvotes: 1