none
Adding Objects to an Array with additional properties

    Question

  • I am having a problem with PowerShell arrays and i don't really understand enough about what is happening to properly search for an answer. Basically i am creating objects in powershell using the New-Object cmdlet and adding those objects to an array. However i don't know how many properties each Object will have because i am dynamically creating those Objects. If the first object added to the array has 3 properties and the second object added to the array has 4 properties the array will contain only 3 properties for each object.

    here are some really simple code examples to illustrate the point. Does anyone know of a way around this behavior?

    $NotWorkingArray = @()
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Yellow"
                    }
    $NotWorkingArray += $Obj
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Blue"
                    Item2 = "Red"
                    }
    $NotWorkingArray += $Obj
    
    
    $NotWorkingArray
    
    Item1 
    ----- 
    Yellow
    Blue 

    $WorkingArray = @()
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Blue"
                    Item2 = "Red"
                    }
    $WorkingArray += $Obj
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Yellow"
                    }
    $WorkingArray += $Obj
    $WorkingArray
    
    Item1  Item2
    -----  -----
    Blue   Red  
    Yellow 

    Friday, November 10, 2017 10:10 PM

All replies

  • No. The array will have all full objects but, when you enumerate the array, the output will, by default, use only the properties of the first object.

    You should not be creating no-identical objects.  Create the object first then assign the values and all will be well.

    Another way to do this is to create  custom type with all properties then just new-up one of these and assign the values.


    \_(ツ)_/


    Friday, November 10, 2017 10:53 PM
    Moderator
  • if you have the possible 'Headers' in hand, try to create only one object in the loop where you create dynamic customobject, set empty values to the particular column if its not applicable for that iteration.

    example:-

    $NotWorkingArray = @()
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Yellow"
                    Item2 = ''
                    }
    $NotWorkingArray += $Obj
    $Obj = New-Object -TypeName PSObject -Property @{
                    Item1 = "Blue"
                    Item2 = "Red"
                    }
    $NotWorkingArray += $Obj


    Regards kvprasoon

    Saturday, November 11, 2017 4:07 AM
  • Hello Parsoon,

    I have used your work around in the past. Define all headers before hand, Do an If/Then check for that properties value and provide a default value if it doesn't exist.

    I was hoping someone had a better idea for times when i know the Headers will change. Lets look at a more specific example. I want to export a list of Azure/O365 licensed users into excel with a column for each license and license feature. The problem is the cmdlet doesn't expose disabled features/licenses. Ultimately i can use this export in excel to filter/sort by users by License and features.

    import-module MSOnline
    connect-msolservice
    
    $AzureLicUsers = Get-MsolUser -All | Where-Object { $_.isLicensed -eq "TRUE" }
    
    $report = @()
    
    foreach ($AzureUser in $AzureLicUsers)
        {
        $rptObject = New-Object -TypeName PSObject
        $rptObject  | Add-Member -MemberType NoteProperty -Name "UPN" -Value $AzureUser.UserPrincipalName
        $licenses = $AzureUser.Licenses
        foreach ($lic in $licenses)
            {
            $rptObject  | Add-Member -MemberType NoteProperty -Name $lic.AccountSkuId -Value "True"
            }
        
        $servicPlans = $AzureUser.Licenses.servicestatus
        Foreach ($servicPlan in $servicPlans)
            {
            $rptObject  | Add-Member -MemberType NoteProperty -Name $servicPlan.ServicePlan.ServiceName -Value $servicPlan.ProvisioningStatus
            }
    
        $report += $rptObject
    
        #$rptObject = $null
        $licenses = $null
        $servicPlans = $null
    
        }
    
    
    $report | Out-String | Export-Csv -NoTypeInformation -Path "c:\csv\AzureUserLicensing2.csv
    for this example i think i can expose all possible licenses and features using the "Get-MsolAccountSku" cmdlet. it would just be easier if i didn't have to go through that work and sometimes i don't have a way to expose headers and i just have to guess. If i ever get time to go back to this code and fix it i will repost here.
    Monday, November 13, 2017 9:00 PM
  • The simplest solution is this:

    $report |select item1,item2,item3 ... | Out-String | Export-Csv -NoTypeInformation -Path "c:\csv\AzureUserLicensing2.csv

    Select all possible fieldsand the selct will crete empty fields for all that are not defined on the object,

    Example:

    ''|select item1,item2,item3,item4


    \_(ツ)_/

    Monday, November 13, 2017 10:28 PM
    Moderator