Combine multiple arrays down to one

AintGotNoTime 161 Reputation points
2021-09-01T19:50:17.237+00:00

In my script I am pulling accounts from many OU structures, and so I have an array for each. how can I eliminate all these different arrays I am trying to combine down to one for the whole things. Sometimes no accounts are returned in the array and I have issues in past that would blank out the main array I was sticking accounts into.
`#Get a domain controller for the dva domain.
$dc = Get-ADDomainController -DomainName dva -Discover -NextClosestSite

Add the Domains via the following

Create and Array and then add the array to the filter with the domain name and then add the filter to main array collections if it finds information

$dvamailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailboxes)" -Server dva | Select-Object -Expand DistinguishedName

After getting the mailbox OU then Create andother array for the accounts and select accounts per the date.

roll through dva looking for accounts

$dvamailboxAccounts = foreach ($box in $($dvamailboxes))
{
Get-ADUser -Server $dc -SearchBase $box -filter * -Property whenCreated | Where {$_.whenCreated -gt $dte}
}

Select the objects from the Get-ADuser and put in an array for use later

$dvaacctArray = $dvamailboxAccounts | select @{Name="userName";Expression={$_.SamAccountName.Trim()}}, @{Name="address";Expression={"dva"}}, @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
@{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, @{Name="secret";Expression={'12345678'}}

Append the array with the DVA accounts

if($dvaacctArray -gt $null)
{
$mainemailaccounts += $dvaacctArray
}
`
Then I do the same with the next domain
#Get the DC for the AAC domain
$dc = Get-ADDomainController -DomainName aac -Discover -NextClosestSite

#Add the Domains via the following
#Create and Array and then add the array to the filter with the domain name and then add the filter to main array collections if it finds information
$aacmailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailbox)" -Server aac |  Select-Object -Expand DistinguishedName


#After getting the mailbox OU then Create andother array for the accounts and select accounts per the date.
#roll through dva looking for accounts
$aacmailboxAccounts = foreach ($box in $($aacmailboxes)) 
    {
        Get-ADUser -Server $dc -SearchBase $box -filter * -Property whenCreated | Where {$_.whenCreated -gt $dte}
    }

#Select the objects from the Get-ADuser and put in an array for use later
$aacacctArray = $aacmailboxAccounts | select @{Name="userName";Expression={$_.SamAccountName.Trim()}}, @{Name="address";Expression={"aac"}}, @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
@{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, @{Name="secret";Expression={'12345678'}}




***But this is where the code will start getting large when trying the meld all the arrays into one as I keep adding more.  How can I reduce this to one arrya otherwise I will end up with about 30 statements like below adding up the arrays.

#Append the array with the AAC accounts
if($aacacctArray -gt $null -and $mainemailaccounts -gt $null)
    {
       $mainemailaccounts += $aacacctArray
    }
        elseif ($aacacctArray -gt $null -and $mainemailaccounts -eq $null)
            {
                $mainemailaccounts += $aacacctArray
            }
            else
                {
                 Write-Output "No accounts exist to onboard"
                 exit 1001
                }
Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,319 questions
{count} votes

Accepted answer
  1. Rich Matheisen 44,416 Reputation points
    2021-09-02T21:20:15.947+00:00

    I think, based on the code you provided, that almost all of the arrays are unnecessary. You can probably wrap up all that your code does in something like this:

    [datetime]$dte = 0      # to be provided
    
    $domains = 'acc','dav'
    [array]$mainemailaccounts = @()
    $domains |
        ForEach-Object{
            #Get the DC for the domain
            $dc = Get-ADDomainController -DomainName $_ -Discover -NextClosestSite |
                Select-Object -Expand distinguishedName -First 1st
            # get the OUs for this domain
            Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailbox)" -Server $dc |  
                Select-Object -Expand DistinguishedName |
                    ForEach-Object{
                        $mainemailaccounts += Get-ADUser -filter * -Server $dc -SearchBase $_ -SearchScope OneLevel -Property whenCreated | 
                                                Where-Object {$_.whenCreated -gt $dte} |
                                                    Select-Object   @{Name="userName";Expression={$_.SamAccountName.Trim()}}, 
                                                                    @{Name="address";Expression={"aac"}}, 
                                                                    @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
                                                                    @{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, 
                                                                    @{Name="secret";Expression={'12345678'}}
                    }
        }
        if ($mainemailaccounts.count -eq 0){
            Write-Output "No accounts exist to onboard"
            exit 1001
        }
    

6 additional answers

Sort by: Most helpful
  1. MotoX80 31,316 Reputation points
    2021-09-02T00:25:44.86+00:00

    A lot of what you posted all runs together and its really hard to read. You should edit your post and use the Code Sample tool (the 101010 icon) to format your code.

    I'll assume that your arrays all contain the same type of object. This example shows how to combine similar named arrays using Get-Variable.

    $ArrArray1 = Get-ChildItem -Path C:\temp\foo1 | foreach { 
        [pscustomobject] @{
            Name = $_.Name 
            Time = $_.LastWriteTime 
        } 
    }
    $ArrArray2 = @()                                                  # an empty array 
    $ArrArray3 = Get-ChildItem -Path C:\windows\temp | foreach { 
        [pscustomobject] @{
            Name = $_.Name 
            Time = $_.LastWriteTime 
        } 
    }
    
    $Combined = @()                                                    # append to this empty array  
    get-variable | foreach {                                           # look at all variables
        if ($_.Name -match 'ArrArray') {          # find our array variables. Use some unique name that will match. 
            "Processing {0}, Count={1}" -f $_.name, $_.Value.count
            $Combined += $_.Value                                # append to our combined array
        }
    }     
    
    "Here is the combined array."
    $Combined 
    ""
    "Total entries = {0}" -f $Combined.Count
    
    0 comments No comments

  2. AintGotNoTime 161 Reputation points
    2021-09-02T17:27:01.353+00:00

    Ok, it exceeded characters on comment but here is the total currently. So I have 33 domains in total to do this, so you can see each time I add another the mesh code at the end will get uncontrollable. i am hoping I can just use one array and keep combining the data with each pull of the domain data.

    #Get a domain controller for the dva domain.
    $dc = Get-ADDomainController -DomainName dva -Discover -NextClosestSite
    
    #Add the Domains via the following
    #Create and Array and then add the array to the filter with the domain name and then add the filter to main array collections if it finds information
    $dvamailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailboxes)" -Server dva |  Select-Object -Expand DistinguishedName
    
    
    #After getting the mailbox OU then Create andother array for the accounts and select accounts per the date.
    #roll through dva looking for accounts
    $dvamailboxAccounts = foreach ($box in $($dvamailboxes)) 
        {
            Get-ADUser -Server $dc -SearchBase $box -filter * -Property whenCreated | Where {$_.whenCreated -gt $dte}
        }
    
    #Select the objects from the Get-ADuser and put in an array for use later
    $dvaacctArray = $dvamailboxAccounts | select @{Name="userName";Expression={$_.SamAccountName.Trim()}}, @{Name="address";Expression={"dva"}}, @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
    @{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, @{Name="secret";Expression={'12345678'}}
    
    #Append the array with the DVA accounts
    if($dvaacctArray -gt $null)
        {
           $mainemailaccounts += $dvaacctArray
        }
    
    
    ####New Mailbox Pull
    #aac mailbox arrays
    $aacmailboxes = @()
    $aacmailboxAccounts = @()
    $aacacctArray = @()
    #Get the DC for the AAC domain
    $dc = Get-ADDomainController -DomainName aac -Discover -NextClosestSite
    
    #Add the Domains via the following
    #Create and Array and then add the array to the filter with the domain name and then add the filter to main array collections if it finds information
    $aacmailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailbox)" -Server aac |  Select-Object -Expand DistinguishedName
    
    
    #After getting the mailbox OU then Create andother array for the accounts and select accounts per the date.
    #roll through dva looking for accounts
    $aacmailboxAccounts = foreach ($box in $($aacmailboxes)) 
        {
            Get-ADUser -Server $dc -SearchBase $box -filter * -Property whenCreated | Where {$_.whenCreated -gt $dte}
        }
    
    #Select the objects from the Get-ADuser and put in an array for use later
    $aacacctArray = $aacmailboxAccounts | select @{Name="userName";Expression={$_.SamAccountName.Trim()}}, @{Name="address";Expression={"aac"}}, @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
    @{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, @{Name="secret";Expression={'12345678'}}
    
    #Append the array with the AAC accounts
    if($aacacctArray -gt $null -and $mainemailaccounts -gt $null)
        {
           $mainemailaccounts += $aacacctArray
        }
            elseif ($aacacctArray -gt $null -and $mainemailaccounts -eq $null)
                {
                    $mainemailaccounts += $aacacctArray
                }
                else
                    {
                     Write-Output "No accounts exist to onboard"
                     exit 1001
                    }
    
    0 comments No comments

  3. MotoX80 31,316 Reputation points
    2021-09-02T19:36:13.11+00:00

    So don't build 33 (or more) arrays, make the "loop" generic so that it can process any domain.

     $ALLmailboxes = @()
     $ALLmailboxAccounts = @()
     $ALLacctArray = @()
     $33Domains = @('aac','dva','abc','xyz','etc')
     Foreach ($Domain in $33Domains) {
         "Processing domain $Domain"
         $Domainmailboxes = @()
         $DomainmailboxAccounts = @()
         $DomainacctArray = @()
    
         $Domainmailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailboxes)" -Server $Domain |  Select-Object -Expand DistinguishedName
    
    
         # rest of domain level processing goes here
    
    
         # All done, Now append the domain that we processed to the overall arrays.  
    
         $ALLmailboxes += $Domainmailboxes 
         $ALLmailboxAccounts += $DomainmailboxAccounts 
         $ALLacctArray += $DomainacctArray
    
    
     }
    
    0 comments No comments

  4. AintGotNoTime 161 Reputation points
    2021-09-03T21:53:37.12+00:00

    Ok, I got this working to filter through so far but 2 things, one it does not pull the samAccountName and I need the address to be the same as the domain I am searching through. I tried the variable but that was a no go.

    [datetime]$dte = '08/15/2021'
    $ALLmailboxes = @()
    $ALLmailboxAccounts = @()
    $ALLacctArray = @()
    $33Domains = @('dva', 'cem')
    
    Foreach ($Domain in $33Domains) {
        $Domainmailboxes = @()
        $DomainmailboxAccounts = @()
        $DomainacctArray = @()
    
        $dc = Get-ADDomainController -DomainName $Domain -Discover -NextClosestSite
        $Domainmailboxes = Get-ADOrganizationalUnit -LDAPFilter "(Name=Shared Mailboxes)" -Server $Domain |  Select-Object -Expand DistinguishedName
    
        Write-Host $Domainmailboxes | Format-Table -force
    
    
        $DomainmailboxAccounts = foreach ($box in $($Domainmailboxes)) 
         {
             Get-ADUser -Server $dc -SearchBase $box -filter * -Property whenCreated | Where {$_.whenCreated -gt $dte}
    
         }
    
        # rest of domain level processing goes here
        $DomainacctArray = $DomainmailboxAccounts | Select
                                                         @{Name="userName";Expression={$_.SamAccountName.Trim()}}, 
                                                         @{Name="address";Expression={'$Domain'}}, 
                                                         @{Name="safeName";Expression={'VA-WIN-MAILBOX-ACCTS'}},
                                                         @{Name="platformId";Expression={'VA-WinLocalDisableAcct-Prod-Admin-26-1yr'}}, 
                                                         @{Name="secret";Expression={'12345678'}}
    
        write-host = $DomainacctArray | Format-table -Force
        # All done, Now append the domain that we processed to the overall arrays.  
    
        #$ALLmailboxes += $Domainmailboxes 
        #$ALLmailboxAccounts += $DomainmailboxAccounts 
        #$ALLacctArray += $DomainacctArray