PowerShell高效创建数组/ArrayList/PSCustomObject及添加对象问题
需求说明
我查了StackOverflow、微软文档等大量资料,还是没搞明白数组创建和对象添加的高效方法。现有示例大多只针对整数或简单值,太简化了。我需要生成能导出为以下格式的CSV,而且要最高效的实现方式(+=操作效率太低,已经明确这点):
OUDN,Inheritancetype,etc OU=Test,Whatever OU=Test,Whatever OU=Brush,Thing OU=Brush,Whatever
当前代码
我现在用的代码如下:
$OUACLResults = @() $OUs = Get-ADOrganizationalUnit -Filter * foreach ($OU in $OUs) { # 额外疑问:我喜欢这种写法,能通过智能提示补全$OU.distinguishedname等属性,管道方式下有没有简便实现方法? $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access Foreach ($ACL in $OUACLs) { # 示例操作:在$ObjectTypeGUID表中查询 $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType) $Object = new-object -typename psobject Add-Member -inputobject $Object -membertype noteproperty -name "OUDN" -value $OU.distinguishedname Add-Member -inputobject $Object -membertype noteproperty -name "Inheritancetype" -value $ACL.Inheritancetype Add-Member -inputobject $Object -membertype noteproperty -name "ObjectType" -value $ObjectType # 其他属性以此类推 # 以下行效率极低 $OUACLResults += $Object } }
遇到的问题
创建$object的部分感觉还行(但用管道结合foreach-object可能更优),但往$OUACLResults里加对象时出问题:
我尝试过把$OUACLResults改成哈希表:
$OUACLresults = @{} $OUACLResults.add($object)
结果报错:No overload for Add and argument count "1"
解决方案
1. 高效收集对象的正确方式(替代+=)
PowerShell里普通数组是固定大小的,+=每次都会创建新数组复制原有数据,数据量一大就会严重拖慢速度。最高效的两种实现方式如下:
方法一:管道链式输出收集(推荐,符合PowerShell原生风格)
把嵌套循环改成管道操作,让代码直接输出自定义对象,最后一次性收集结果,不需要手动维护数组:
$OUACLResults = Get-ADOrganizationalUnit -Filter * | ForEach-Object { $currentOU = $_ # 保存当前OU对象,编辑器可识别类型并提供属性智能提示 $OUACLs = Get-Acl "ad:\$($currentOU.DistinguishedName)" | Select-Object -ExpandProperty Access $OUACLs | ForEach-Object { $ObjectType = $ObjectTypeGUID.Item($_.ObjectType) # 用[PSCustomObject]直接创建对象,比New-Object+Add-Member更高效简洁 [PSCustomObject]@{ OUDN = $currentOU.DistinguishedName Inheritancetype = $_.InheritanceType ObjectType = $ObjectType # 其他属性直接追加键值对即可 } } } # 直接导出CSV $OUACLResults | Export-Csv -Path "OU_ACLs.csv" -NoTypeInformation
方法二:用ArrayList动态数组
如果习惯用循环手动添加,改用System.Collections.ArrayList,它的Add方法直接在原有集合追加,不会频繁创建新数组:
$OUACLResults = New-Object System.Collections.ArrayList $OUs = Get-ADOrganizationalUnit -Filter * foreach ($OU in $OUs) { $OUACLs = (Get-Acl "ad:\$($OU.DistinguishedName)").Access foreach ($ACL in $OUACLs) { $ObjectType = $ObjectTypeGUID.Item($ACL.ObjectType) $Object = [PSCustomObject]@{ OUDN = $OU.DistinguishedName Inheritancetype = $ACL.InheritanceType ObjectType = $ObjectType } # 加[void]抑制Add方法返回的索引值输出,避免控制台冗余信息 [void]$OUACLResults.Add($Object) } } $OUACLResults | Export-Csv -Path "OU_ACLs.csv" -NoTypeInformation
2. 哈希表报错的原因
@{}创建的是哈希表(键值对集合),它的Add方法必须传入两个参数:键和值,比如$OUACLResults.Add("唯一标识", $object),你只传了一个对象参数,所以触发重载错误。哈希表不适合用来收集要导出CSV的对象列表,应该用数组或ArrayList。
3. 优化对象创建
用[PSCustomObject]@{}是PowerShell 3.0+推荐的自定义对象创建方式,比New-Object搭配Add-Member代码更简洁,执行效率也更高。
内容的提问来源于stack exchange,提问作者Badger

