For you information, "Set-PnPUserSPOUser" works only if your account is already granted as site collection administrator and is not compatible with PnP contexts.
Import-Module SharePointPnPPowerShellOnline
$tenantName = "<YOUR_TENANT_NAME>"
$localeId = 2057 # UK
$timeZoneId = 2 # London
#Connect to SPO Tenant
$cnx = Connect-PnPOnline "https://$tenantName-admin.sharepoint.com" -UseWebLogin -ReturnConnection
#Get Tenant CSOM instance
$tenant = new-object Microsoft.Online.SharePoint.TenantAdministration.Tenant([Microsoft.SharePoint.Client.ClientRuntimeContext]$cnx.Context)
function Remove-PnPTenantSiteCollectionAdministrator{
param([string]$siteUrl, [string[]]$users)
$ctx = $tenant.Context;
$targetSite = $tenant.GetSiteByUrl($siteUrl);
$ctx.Load($targetSite);
$ctx.ExecuteQuery();
$users |%{
$user = $targetSite.RootWeb.EnsureUser($_);
$ctx.Load($user)
$ctx.ExecuteQuery();
if($user.IsSiteAdmin){
$user.IsSiteAdmin = $false;
$user.Update();
}
}
$ctx.ExecuteQuery();
}
function Get-PnPTenantSiteAuthor{
param([string]$siteUrl)
$ctx = $tenant.Context;
$targetSite = $tenant.GetSiteByUrl($siteUrl);
$author = $targetSite.RootWeb.Author
$ctx.Load($author);
$ctx.ExecuteQuery()
[pscustomobject]@{
LoginName = $author.LoginName
DisplayName = $author.Title
UserPrincipalName = $author.UserPrincipalName
Email = $author.Email
}
}
#Get current UserName
$tenantWeb = Get-PnPWeb
$tenantWeb.Context.Load($tenantWeb.CurrentUser)
$tenantWeb.Context.ExecuteQuery()
$currentUser = $tenantWeb.CurrentUser
#Get All sites then execute
Get-PnPTenantSite | %{
$site = $_;
#Grant current user as admin if it's not already it's own
if($site.OwnerEmail -ne $currentUser.Email){
$site.Url | Set-PnPTenantSite -Owners $currentUser.Email |out-null
}
$user = Get-PnPTenantSiteAuthor $site.Url
try{
$ctx = $tenant.Context;
$targetSite = $tenant.GetSiteByUrl($site.Url);
$web = $targetSite.RootWeb;
$timeZones = $web.RegionalSettings.TimeZones
$ctx.Load($timeZones)
$ctx.ExecuteQuery()
$timeZone = $timeZones | ?{ $_.Id -eq $timeZoneId }
$web.RegionalSettings.LocaleId = $localeId
$web.RegionalSettings.TimeZone = $timeZone
$web.Update()
$ctx.ExecuteQuery()
}
finally{
#Remove Current User as admin except for it's own
if($site.OwnerEmail -ne $currentUser.Email){
Remove-PnPTenantSiteCollectionAdministrator $site.Url $currentUser.LoginName |out-null
}
#ensure owner is the real owner
if([string]::IsNullOrEmpty($site.Owner)){
$site.Url | Set-PnPTenantSite -Owners $res$user.UserPrincipalName |out-null
}
}
}