PowerShell不会创建数组

时间:2018-01-31 08:34:17

标签: powershell active-directory

我有这个问题很长一段时间,只要我认为它会输出它没有输出的所有数据。

示例:

$groups = "group1","Group2","Group3" # to be excluded
foreach ($group in $groups) {
    $dns = (Get-ADGroup "$Group").DistinguishedName
}
Write-Host $dns

将仅输出一个组的专有名称,但如果同时输出

(Get-ADGroup "$Group").DistinguishedName | Out-File c:\list.txt

我将获得所有3.如果我尝试从阵列中获取用户,那么`Get-ADUser也是如此。

任何人都有真正的解决方案吗?

2 个答案:

答案 0 :(得分:2)

PowerShell并不会因为你的意愿而神奇地创建一个数组。由于$dns从一开始就不是一个数组,所以你的代码会在每次迭代时替换它的值,所以你最终只得到循环结束后的最后一个值。

您有2种方法可以解决此问题:

  • 在循环之前将$dns定义为数组,并在循环内附加到该数组。

    $dns = @()
    foreach ($group in $groups) {
        $dns += (Get-ADGroup "$Group").DistinguishedName
    }
    

    虽然几乎每个人似乎都是这样做的,但出于性能原因,该方法 NOT WOMMENDED 。附加到数组是很昂贵的,因为它实际上创建了一个大小增加的新数组,移动所有现有元素并将新元素放入新的空闲插槽中,然后替换原始数组。

  • 在循环内输出结果,并在变量中收集整个循环输出。

    $dns = foreach ($group in $groups) {
        (Get-ADGroup "$Group").DistinguishedName
    }
    

    这种方法比在循环中附加方法具有明显更好的性能。但是,值得注意的是,如果循环产生零个或一个元素,结果将是$null或简单值,而不是数组。您可以通过将循环放在数组构造运算符中来强制它到数组:

    $dns = @(foreach ($group in $groups) {
        (Get-ADGroup "$Group").DistinguishedName
    })
    

附录:正如@Clijsters在评论中提到的那样,使用.Net集合而不是基本的PowerShell数组实际上是第三种解决此问题的方法:

$dns = New-Object System.Collections.ArrayList
foreach ($group in $groups) {
    $dns.Add((Get-ADGroup "$Group").DistinguishedName) | Out-Null
}

附加到集合远比附加到PowerShell数组要便宜。但是,实例化集合会有一些开销。只需在变量($dns = foreach (...) {...})中收集循环输出,即可获得最佳性能。

答案 1 :(得分:1)

问题是您的Write-Host

$groups = "Group1", "Group2", "Group3"
foreach ($group in $groups) {
    $dns = (Get-ADGroup $group).DistinguishedName
    Write-Host $dns # <--- it's inside, now!
}

这将为每个组写出值,而不仅仅是 last