Zoltán
Zoltán

Reputation: 135

creating PowerShell custom objects

I created a custom object in PowerShell. I was able to solve the problem I wanted to solve. I wanted to have an object with two columns, one for the site collection, one for the email.

However, I am wondering if there is an easier solution. Do you have any suggestions?

Here is my code:

$cred = Get-Credential

Connect-PnPOnline "https://tenant.sharepoint.com" -Credentials $cred
$SiteCollections = Get-PnPTenantSite

$object = @()

foreach ($SiteCollection in $SiteCollections) {
    Connect-PnPOnline -Url $SiteCollection.Url -Credentials $cred
    $email = Get-PnPRequestAccessEmails
    Write-Host "Email for $($SiteCollection.Url): $($email)"

    $obj = New-Object System.Object
    $obj | Add-Member -type NoteProperty -name Url -value $SiteCollection.Url
    $obj | Add-Member -type NoteProperty -name Email -value $email
    $object += $obj
}

Write-Output $object

Upvotes: 12

Views: 15476

Answers (3)

user3723688
user3723688

Reputation: 47

Especially if your array is going to get very large, you might want to consider using an arraylist instead of a vanilla array. With a standard array, every time you add data to it, it recreates the whole array, as opposed to just tacking your data on the end. An arraylist simply appends and is much faster for building large arrays.

$outArray = New-Object System.Collections.ArrayList

foreach ($SiteCollection in $SiteCollections) {
    Connect-PnPOnline -Url $SiteCollection.Url -Credentials $cred
    $email = Get-PnPRequestAccessEmails
    Write-Host "Email for $($SiteCollection.Url): $($email)"

    $obj = New-Object System.Object
    $obj | Add-Member -type NoteProperty -name Url -value $SiteCollection.Url
    $obj | Add-Member -type NoteProperty -name Email -value $email
    [void]$outArray.Add($obj)
}

Upvotes: 0

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200193

Objects can be constructed from a hashtable either with the New-Object cmdlet:

$obj = New-Object -Type PSObject -Property @{
    'Url'   = $SiteCollection.Url
    'Email' = $email
}

or (if you have PowerShell v3 or newer) the [PSCustomObject] type accelerator:

$obj = [PSCustomObject]@{
    'Url'   = $SiteCollection.Url
    'Email' = $email
}

Also, you can simply output the objects inside the loop and collect the entire loop output in a variable like this:

$object = @(foreach ($SiteCollection in $SiteCollections) {
    ...
    New-Object -Type PSObject -Property @{
        'Url'   = $SiteCollection.Url
        'Email' = $email
    }
})

The array subexpression operator (@()) around the foreach loop ensures that the result is an array, even if the loop output is less than 2 objects.

Using a calculated property would be another option:

$object = @(Get-PnPTenantSite | Select-Object Url, @{n='Email';e={
    Connect-PnPOnline -Url $_.Url -Credentials $cred | Out-Null
    Get-PnPRequestAccessEmails
}})

Upvotes: 21

Bill_Stewart
Bill_Stewart

Reputation: 24515

Shortening the code a bit:

$cred = Get-Credential
Get-PnPTenantSite | ForEach-Object {
  Connect-PnPOnline -Url $_.Url -Credentials $cred
  [PSCustomObject] @{
    Url = $_.Url
    Email = Get-PnPRequestAccessEmails
  }
}

The [PSCustomObject] type accelerator only exists in PowerShell 3.0 and later.

Upvotes: 3

Related Questions