arrayspowershellpsobject

PowerShell - most efficient way to create an array/arraylist/pscustomobject


I've done a lot of reading around this from StackOverflow, Microsoft, and other sources, but struggling to come to grips with creating and adding objects to arrays. Most of the examples I can find are overly simplistic with just integers, or simple values. I know this is not the best way below, but is just to give an example of what I am trying to do in this instance. I want something I can output to CSV which would have something like the following, and in the most efficient way (obviously += is bad):

OUDN,Inheritancetype,etc  
OU=Test,Whatever  
OU=Test,Whatever  
OU=Brush,Thing  
OU=Brush,Whatever
$OUACLResults = @()
$OUs = Get-ADOrganizationalUnit -Filter *

foreach ($OU in $OUs)
{
        # additional question, I like doing it this way so I can easily use intellisense to complete the attributes like $OU.distinguishedname, is there an easy way to do this when piping?

        $OUACLs = (get-ACl ad:\$OU.Distinguishedname).access

        Foreach ($ACL in $OUACLs)
        {

              #example of other work required, this is doing a lookup in table $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
              #and so on for other attributes

              #next line particularly inefficient
              $OUACLResults += $Object

         }

}

The $object part above seems efficient, from what I have seen (although piping and using foreach-obj might be better), but it is adding the $object to $OUACLResults that is not working:

#tried 
$OUACLresults = @{}
$OUACLResults.add($object) 

#no overload for Add and argument count "1"

Solution

  • @{} creates a hashtable - an unordered dictionary - you'll want to create a list instead:

    $OUACLResults = [System.Collections.Generic.List[psobject]]::new()
    

    Then in the loop body:

    $OUACLResults.Add($object)
    

    Additionally, using the [pscustomobject]@{ ... } shorthand syntax for object creation is generally much faster than New-Object + Add-Member:

    $object = [pscustomobject]@{
      OUDN = $OU.distinguishedname
      Inheritancetype = $ACL.Inheritancetype
      ObjectType = $ObjectType
    }