Formatting a powershell custom object

;-}
Olaf… yeah… maybe I should have left that part off.
;-}

Since a code sample was already given, seemed like a fun challenge to see if it can be done simpler

#Sample Data
$data = [pscustomobject]@{
            'Group Policy' = 'GPO1'
            'Group' = 'test\Group1'
            'MemberOf' = 'Builtin\BackupOperator'
        },
        [pscustomobject]@{
            'Group Policy' = 'GPO1'
            'Group' = 'test\Group2'
            'MemberOf' = 'Builtin\RemoteDesktopUsers'
        },
        [pscustomobject]@{
            'Group Policy' = 'GPO1'
            'Group' = 'test\Group3'
            'MemberOf' = 'Builtin\PowerUsers'
        },
        [pscustomobject]@{
            'Group Policy' = 'GPO2'
            'Group' = 'test\Group4'
            'MemberOf' = 'Builtin\BackupOperator'
        },
        [pscustomobject]@{
            'Group Policy' = 'GPO2'
            'Group' = 'test\Group5'
            'MemberOf' = 'Builtin\RemoteDesktopUsers'
        },
        [pscustomobject]@{
            'Group Policy' = 'GPO2'
            'Group' = 'test\Group6'
            'MemberOf' = 'Builtin\PowerUsers'
        }

#Sample Code
$data | ForEach-Object {
    If ($_.'Group Policy' -eq $groupfirstobject.'Group Policy') {
        $_.'Group Policy' = $null
        $_
    }
    Else {
        $groupfirstobject = $_
        $_
    }  
}

Of course you can then export to csv if you like

#Sample Code
$data | ForEach-Object {
    If ($_.'Group Policy' -eq $groupfirstobject.'Group Policy') {
        $_.'Group Policy' = $null
        $_
    }
    Else {
        $groupfirstobject = $_
        $_
    }
    
} | Export-Csv d:\test\test.csv -NoTypeInformation

Sample Results

Group Policy Group       MemberOf                  
------------ -----       --------                  
GPO1         test\Group1 Builtin\BackupOperator    
             test\Group2 Builtin\RemoteDesktopUsers
             test\Group3 Builtin\PowerUsers        
GPO2         test\Group4 Builtin\BackupOperator    
             test\Group5 Builtin\RemoteDesktopUsers
             test\Group6 Builtin\PowerUsers

 

Thanks Curtis. I will try it out today and let you know if it works or not. However I hope I do not need to populate the $data variable manually as done in the above code as there are 100’s of GPO’s. I put two GPO’s just as an example.

Also would you explain a bit of the logic behind the below code:

$data | ForEach-Object {
If ($.‘Group Policy’ -eq $groupfirstobject.‘Group Policy’) {
$
.‘Group Policy’ = $null
$_
}
Else {
$groupfirstobject = $_
$_
}

} | Export-Csv d:\test\test.csv -NoTypeInformation

 

Like $groupfirstobject.‘Group Policy’ what is this going to do?

Please start to format the code as code here in the forum using the code tag button (pre) on the post editor (second to last button).
Thanks

I see others have joined the fray before I got back to this.
After finally getting back to a DC, I see Chris, got here before I did, but he is using static entries.
I was reworking mine, to keep it dynamic. So …

$GpoData = @()

Get-GPO -All | 
ForEach {
$GpoData += [pscustomobject]@{
            'GroupPolicy'  = $PSItem.DisplayName
            'Group'        = $PSItem.Owner
            'MemberOf'     = (Get-ADGroupMember -Identity ($($PSItem.Owner) -replace '.*\\'))
        }
}

$CurrentPolicy = $null

ForEach ($Policy in $GpoData)
{
    # $Policy.GroupPolicy
    # $Policy.MemberOf.SamAccountName

    ForEach($Member in $Policy.MemberOf.SamAccountName)
    {
        If($Policy.GroupPolicy -ne $CurrentPolicy)
        {
            [pscustomobject]@{
                'GroupPolicy' = $Policy.GroupPolicy
                'Group'       = $Policy.Group
                'Member'      = $Member
            }
        }
        Else
        {
            [pscustomobject]@{
                'GroupPolicy' = ''
                'Group'       = $Policy.Group
                'Member'      = $Member
            }        
        }

        $CurrentPolicy = $Policy.GroupPolicy
    }
}

# Results

GroupPolicy                           Group                   Member
-----------                                             -----                   ------                  
Default Domain Policy                 Contoso\Domain Admins  Administrator
                                      Contoso\Domain Admins  adcsadmin
                                      Contoso\Domain Admins  adfsadmin
...
Default Domain Controllers Policy     Contoso\Domain Admins  Administrator
                                      Contoso\Domain Admins  adcsadmin
                                      Contoso\Domain Admins  adfsadmin
...

[quote quote=158180]Thanks Curtis. I will try it out today and let you know if it works or not. However I hope I do not need to populate the $data variable manually as done in the above code as there are 100’s of GPO’s. I put two GPO’s just as an example.

Also would you explain a bit of the logic behind the below code:

$data | ForEach-Object {

If ($_.‘Group Policy’ -eq $groupfirstobject.‘Group Policy’) {

$_.‘Group Policy’ = $null

$_

}

Else {

$groupfirstobject = $_

$_

}

} | Export-Csv d:\test\test.csv -NoTypeInformation

Like $groupfirstobject.‘Group Policy’ what is this going to do?

[/quote]

You never actually provided information on how you were getting your data. IE via Spreadsheet, a commandlet, something else? So I just made custom PSObject that represented the data in the format you provided. You can adjust it to be whatever datasource you want.

What the code is doing is very simple:

  1. It Pipes the dataset to ForEach-Object
  2. It look at the current object and sees if the "Group Policy" property on that object matches the "Group Policy" property on the object in variable $groupfirstobject (When the first object comes down the pipeline $groupfirstobject will be null so it will not match)
  3. If it does not match, it sets $groupfirstobject to be the same as the current object in the ForEach-Object and then sends the current object to the pipeline
  4. The next object that comes down the will be checked against $groupfirstobject to see if their "Group Policy" properties match just like before except this time $groupfirstobject contains the first object that came down the pipeline
  5. If it matches, then it just sets the "Group Policy" property on the current object to $null, basically blanking out this property so it is seen as blank when output to the shell or CSV, then send the updated object with a blank "Group Policy" property to the pipeline
  6. If it does not match, then this is a new Group Policy group, so it updates the $groupfirstobject variable to be this current object and repeats the process outlined above

Thanks Curtis for the explanation. I can understand it now and I tried the code it works fine also.