You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell高效创建数组/ArrayList/PSCustomObject及添加对象问题

PowerShell高效处理AD OU ACL并导出CSV的问题

需求说明

我查了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 14:07:09