TLDR; Use Where Instead of -filter

I had a request to give a specific user account Site Collection Admin (SCA) rights a group of Modern Team sites in SharePoint Online. My friend Daniel has previously created a script to give a user account SCA rights to all the sites in the tenant.  I knew I could use create a variable $a  and then use Get-SPOSite and filter by some of the site properties.

I also know I could do a foreach of $a and have it return the site collection then I could do some magic against the objects.

Step 1

So my first attempt to find all the site collections that were “-like” the url I was looking for, was to try

$a = Get-SPOSite -Filter
(Now I tried this because https://docs.microsoft.com/en-us/powershell/module/sharepoint-online/get-sposite?view=sharepoint-ps said I could use -filter.)

So of course I tried

$a = Get-SPOSite -Filter {$_.url -like ‘https://tenant.sharepoint.com/sites/Project_*‘}

And of course I get an error.

Get-SPOSite : Filtering is not supported for property $_.url.

So clearly the error was telling me that I can’t use -filter with the property $_.url, but I naturally assumed it was something else, like maybe I needed to add my -limit All to the command. (Because I’m an idiot most of the time)

Of course failure again.

After banging my head against a wall for a bit, and thinking maybe I should just do one site at a time using the GUI (Manually doing a repeatable task now, when you can automate it forever.” could be the worst failure possible. It could also just be stubbornness that takes you twice or three times as long to do something, but hey you know you’re gonna need to do this again. :))

I realized Filter was probably just not going to work, and maybe the clear error truly was correct. (I rarely say this about SharePoint, so +20 SharePoint Online Reputation Score, or maybe @Vesa Juvonen and his incredible SharePoint PnP team ?)

So my next thought was how would I do this in PowerShell for something like on premises. So normally I’d use something and use a pipe to a where-object. So something like $a = Get-SPOSite | Where {$_.Url -like ‘https://tenant.sharepoint.com/sites/Project_*‘}

 

And Guess what! That worked. (I should probably throw a -Limit All to my Get-SPOSite before I pipe it, because reasons.)

So Step 1 done.
$a = Get-SPOSite -Limit All | Where {$_.Url -like ‘https://tenant.sharepoint.com/sites/Project_*‘}

Step 2

Now I know I just need to use the Set-SPOUser cmdlet available to us.

Set-SPOUser -site $a -LoginName myaccount@tenant.onmicrosoft.com -IsSiteCollectionAdmin $True

But I need to fix a couple things, like I should use a variable for my LoginName, and also the script above, is only going to update 1 site collection, and my plan is to update all of the site collections.

So looks like we need a variable for my user

$NewUser = “myaccount@tenant.onmicrosoft.com”

And let’s use ForEach so we can get each site collection… do some magic to it and then move to the next.

Foreach ($b in $a)
{
Set-SPOUser -site $b -LoginName $NewUser -IsSiteCollectionAdmin $True

}

And boom. That’s it. Now of course that code is ugly so cleaned it up a little bit and here’s the full script below.

Step 3.
Put it all together.

# PowerShell script using SharePoint PNP online
# Add Site Collection Admin to Site Collection that match a URL filter
#

$NewUser = “myaccount@tenant.onmicrosoft.com”
$tenant = “tenant”
$tenantUrl = “https://”+$tenant+”-admin.sharepoint.com”

Connect-SPOService -url $tenantUrl

$sites = Get-SPOSite -Limit All | Where {$_.Url -like ‘https://tenant.sharepoint.com/sites/Project_*‘}
Foreach ($site in $sites)
{
Set-SPOUser -site $site -LoginName $NewUser -IsSiteCollectionAdmin $True
Write-Host “Added $NewUser as Site Collection Admin to the site” $Site.Url
}

(12)