Jun 12 2018 05:33 AM
In Office 365, the SharePoint "Save as Site template" is not available anymore.
In many case, this strategy was used by power users to create a templated site they can save and use after for the new site respecting that format (cupcake notion).
In SharePoint Online, that option is not possible and Microsoft will not invite the users to create the subsites as much as possible, the solution concept is now flat and not anymore hierarchal.
SharePoint Online is only a branch of all the applications or tools given with an Office 365 Group.
But for many cases, we need to continue that usage of template (preparing the Cupcake) to industrialize some repeated activities (projects, analysis, assessment, …).
So now, the only way is to think about that industrialization with PowerShell Scripting.
Into that page, you will find 2 versions I wrote for my needs, but you can easily adapt it:
---------------------------------------------------------
CSOM PowerShell script:
This one is based on many articles I found on Internet associated with my development, so the sources which help me:
Feel free to adapt and use it as you need.
# VALUE TO ADAPT !!!!! # -------------------------------------------------------------------------------------------- $SiteIntegrationUrl ="https://tenant.sharepoint.com/sites/SiteCollection/Subsite1" $SubSiteURL = "testsubsite" $SubSiteName ="_TESTSUBSITE" $EmailAddressAccessRequest = "emailaddresstosupport@domain.com" $RootSiteOwnerGroup = "Root Site Collection Owners" # -------------------------------------------------------------------------------------------- function Load-DLLandAssemblies { [string]$defaultDLLPath = "" # Load assemblies to PowerShell session $defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll" [System.Reflection.Assembly]::LoadFile($defaultDLLPath) $defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll" [System.Reflection.Assembly]::LoadFile($defaultDLLPath) $defaultDLLPath = "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.Online.SharePoint.Client.Tenant.dll" [System.Reflection.Assembly]::LoadFile($defaultDLLPath) } #Custom Function to Check if Site Collection Exists in Given URL Function Check-SiteExists($MySiteURL, $MyCredentials) { #Setup context $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($MySiteURL) $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($MyCredentials.UserName,$MyCredentials.Password) $Web = $Ctx.Web $Ctx.Load($web) Try { $Ctx.ExecuteQuery() Return $True } Catch [Exception] { Write-host " >>>> ERROR MESSAGE:", $_.Exception.Message -f Red Return $False } } Function Create-SPWebList([string]$MyShortTitle, [string]$MyDescription, [int]$MyListTemplateType, [Microsoft.SharePoint.Client.ClientContext]$Mycontext) { Write-Host " ---------------------------------------------------------" $lci = New-Object Microsoft.SharePoint.Client.ListCreationInformation $lci.Title = $MyShortTitle $lci.Description = $MyDescription $lci.TemplateType = $MyListTemplateType #see: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splisttemplatetype.aspx $list = $Mycontext.web.lists.add($lci) $Mycontext.load($list) #send the request containing all operations to the server try{ $Mycontext.executeQuery() write-host " >>> info: List Created $($MyShortTitle)" -foregroundcolor green } catch{ write-host " >>> List Creation Error info: $($_.Exception.Message)" -foregroundcolor red } Write-Host " ---------------------------------------------------------" } # --------------------------------------------------------------------------------------------------------------- Load-DLLandAssemblies #get and save your O365 credentials [string]$username = "AdminSiteCollection@tenant.onmicrosoft.com" [string]$PwdTXTPath = "C:\SECUREDPWD\ExportedPWD-$($username).txt" $secureStringPwd = ConvertTo-SecureString -string (Get-Content $PwdTXTPath) $cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd $DocLibTitleLong = "Given Documents" $DocLibTitle = -join($SubSiteURL, "GivenDocuments") $DocLibTitleLong = -join($SubSiteName, " Given Documents") $SubSiteTitle = -join($SubSiteName, " - Subsite Usage") $SubSiteOwnerOwners = -join($SubSiteName, " Subsite Usage Web Owners") $SubSiteOwnerMembers = -join($SubSiteName, " Subsite Usage Web Members") $SubSiteOwnerVisitors = -join($SubSiteName, " Subsite Usage Web Visitors") $SubSiteFullUrl = -join($SiteIntegrationUrl, "/", $SubSiteURL) # --------------------------------------------------------------------------------------------------------------- #connect to the web site using the stored credentials Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- CONNECT THE SITE --- " -ForegroundColor green Write-host " CONNECTED SITE:", $SiteIntegrationUrl -ForegroundColor Yellow $Myctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteIntegrationUrl) $Myctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($cred.UserName,$cred.Password) $Myctx.RequestTimeout = 1000000 # milliseconds $MyspoRootweb = $Myctx.Web $Myctx.Load($MyspoRootweb) $Myctx.ExecuteQuery() Write-Host " " Write-Host " ---------------------------------------------------------" Write-Host " >>>> # Server Version:" $Myctx.ServerVersion " # <<<<<<" -ForegroundColor Green Write-Host " ---------------------------------------------------------" Write-Host " " Write-host " -------------------------------------------------------- " Write-host " -->> RootSite:", $MyspoRootweb.URL -ForegroundColor green Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- START THE SUBSITE CREATION --- " -ForegroundColor green Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green $SiteExists = Check-SiteExists $SubSiteFullUrl $cred if($SiteExists -ne $true) { Write-host " NEW SITE URL TO CREATE:", $SubSiteFullUrl -ForegroundColor Yellow $Subsite = New-Object Microsoft.SharePoint.Client.WebCreationInformation $Subsite.WebTemplate = "STS#0" $Subsite.Title = $SubSiteTitle $Subsite.Url = $SubSiteURL $Subsite.Language = "1033" $Subsite.Description = $SubSiteTitle $SubWeb = $Myctx.Web.Webs.Add($Subsite) $Myctx.Load($SubWeb) Try{ $Myctx.ExecuteQuery() Write-host " " Write-host " >> Success info creating site for $SubSiteURL" -ForegroundColor green } Catch{ Write-host " >> Error info creating subsite for $SubSiteURL - $_.Exception.Message" -ForegroundColor red } $context = New-Object Microsoft.SharePoint.Client.ClientContext($SubSiteFullUrl) $context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($cred.UserName,$cred.Password) $web = $context.web $context.load($web) Write-host " " Write-host " Implement the Top menu navigation" -ForegroundColor green $web.Navigation.UseShared = $true $context.ExecuteQuery(); Write-host " " Write-host " Implement the Access Request settings: ", $EmailAddressAccessRequest -ForegroundColor green $Web.RequestAccessEmail = $EmailAddressAccessRequest $web.breakroleinheritance($false, $false) $web.update() $context.ExecuteQuery(); $AllSiteCollectionGroups = $web.SiteGroups $context.Load($AllSiteCollectionGroups) $context.executeQuery() $existingRootSiteOwnerGroup = $AllSiteCollectionGroups.getByName($RootSiteOwnerGroup) Write-host " " Write-host " Default Root site group", $existingRootSiteOwnerGroup -ForegroundColor green Write-host " " $PermissionLevel = $context.Web.RoleDefinitions.GetByName("Full Control") #Bind Permission Level to Group $RoleDefBind = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context) $RoleDefBind.Add($PermissionLevel) $Assignments = $context.Web.RoleAssignments $RoleAssignOneNote = $Assignments.Add($existingRootSiteOwnerGroup,$RoleDefBind) $context.Load($existingRootSiteOwnerGroup) #send the request containing all operations to the server try{ $context.executeQuery() Write-host " " write-host " >> Success info: Added Root site group with Full Control" -foregroundcolor green } catch{ Write-host " " write-host " >> Error info: $($_.Exception.Message)" -foregroundcolor red } #Create new groups $MysiteGroups = $SubSiteGroupOwners, $SubSiteGroupMembers, $SubSiteGroupVisitors foreach ($siteGroup in $MysiteGroups){ if ($siteGroup -like "*Web Visitors") { Write-host " " Write-host " Creation of the Visitors group", $SubSiteGroupVisitors -ForegroundColor green $gci = New-Object Microsoft.SharePoint.Client.GroupCreationInformation $gci.Title = $siteGroup $gci.Description = $siteGroup $siteGroup = $context.Web.SiteGroups.Add($gci) $PermissionLevel = $context.Web.RoleDefinitions.GetByName("Read") #Bind Permission Level to Group $RoleDefBind = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context) $RoleDefBind.Add($PermissionLevel) $Assignments = $context.Web.RoleAssignments $RoleAssignOneNote = $Assignments.Add($siteGroup,$RoleDefBind) $context.Load($siteGroup) $context.Web.Update() #send the request containing all operations to the server try{ $context.executeQuery() write-host " >> Success info: Added visitors group" -foregroundcolor green } catch{ write-host " >> Error info: $($_.Exception.Message)" -foregroundcolor red } } if ($siteGroup -like "*Web Members") { Write-host " " Write-host " Creation of the Members group", $SubSiteGroupMembers -ForegroundColor green $gci = New-Object Microsoft.SharePoint.Client.GroupCreationInformation $gci.Title = $siteGroup $gci.Description = $siteGroup $siteGroup = $context.Web.SiteGroups.Add($gci) $PermissionLevel = $context.Web.RoleDefinitions.GetByName("Edit") #Bind Permission Level to Group $RoleDefBind = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context) $RoleDefBind.Add($PermissionLevel) $Assignments = $context.Web.RoleAssignments $RoleAssignOneNote = $Assignments.Add($siteGroup,$RoleDefBind) $context.Load($siteGroup) $context.Web.Update() #send the request containing all operations to the server try{ $context.executeQuery() write-host " >> Success info: Added members group" -foregroundcolor green } catch{ write-host " >> Error info: $($_.Exception.Message)" -foregroundcolor red } } if ($siteGroup -like "*Web Owners") { Write-host " " Write-host " Creation of the Owners group", $SubSiteGroupOwners -ForegroundColor green $gci = New-Object Microsoft.SharePoint.Client.GroupCreationInformation $gci.Title = $siteGroup $gci.Description = $siteGroup $siteGroup = $context.Web.SiteGroups.Add($gci) $PermissionLevel = $context.Web.RoleDefinitions.GetByName("Full Control") #Bind Permission Level to Group $RoleDefBind = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context) $RoleDefBind.Add($PermissionLevel) $Assignments = $context.Web.RoleAssignments $RoleAssignOneNote = $Assignments.Add($siteGroup,$RoleDefBind) $context.Load($siteGroup) $context.Web.Update() #send the request containing all operations to the server try{ $context.executeQuery() write-host " >> Success info: Added owners group" -foregroundcolor green } catch{ write-host " >> Error info: $($_.Exception.Message)" -foregroundcolor red } } } Write-host " " Write-host " Get the Site groups" -ForegroundColor green $context.Load($AllSiteCollectionGroups) $context.executeQuery() Write-host " " Write-host " Update the Groups owners to:", $existingRootSiteOwnerGroup.Id -ForegroundColor green $MyOwnersGroup = $AllSiteCollectionGroups.GetByName($SubSiteGroupOwners) $MyMembersGroup = $AllSiteCollectionGroups.GetByName($SubSiteGroupMembers) $MyVisitorsGroup = $AllSiteCollectionGroups.GetByName($SubSiteGroupVisitors) $MyOwnersGroup.Owner = $existingRootSiteOwnerGroup $MyOwnersGroup.Update() $MyMembersGroup.Owner = $existingRootSiteOwnerGroup $MyMembersGroup.Update() $MyVisitorsGroup.Owner = $existingRootSiteOwnerGroup $MyVisitorsGroup.Update() $context.executeQuery() Write-host " " Write-host " >>>>> in Case of error, you have to go on the default group page: $($SubSiteFullUrl)/_layouts/15/permsetup.aspx " -ForegroundColor magenta # : /_layouts/15/permsetup.aspx Write-host " " Write-host " Define the Default SPWeb groups" -ForegroundColor green $context.Load($web) $context.executeQuery() Write-host " Check the values !!!" Write-host " >>> AssociatedVisitorGroup:", $web.AssociatedVisitorGroup.Id -ForegroundColor Magenta Write-host " >>> AssociatedMemberGroup:", $web.AssociatedMemberGroup.Id -ForegroundColor Magenta Write-host " >>> AssociatedMemberGroup:", $web.AssociatedOwnerGroup.Id -ForegroundColor Magenta Write-host " " Write-host " Define the Visitors group:", $MyVisitorsGroup.Id -ForegroundColor green $web.AssociatedVisitorGroup = $MyVisitorsGroup $web.AssociatedVisitorGroup.Update() Write-host " " Write-host " Define the Members group:", $MyMembersGroup.Id -ForegroundColor green $web.AssociatedMemberGroup = $MyMembersGroup $web.AssociatedMemberGroup.Update() Write-host " " Write-host " Define the Owners group:", $MyOwnersGroup.Id -ForegroundColor green $web.AssociatedOwnerGroup = $MyOwnersGroup $web.AssociatedOwnerGroup.Update() $web.Update() $context.executeQuery() #Create the Doc Lib Write-host " " Write-host " Create Doc Lib:", $DocLibTitle -ForegroundColor green Create-SPWebList $DocLibTitle $DocLibTitleLong 101 $context $MyList = $context.Web.Lists.GetByTitle($DocLibTitle) $context.Load($MyList) $context.executeQuery() $MyList.Title = $DocLibTitleLong $MyList.OnQuickLaunch = $True $MyList.Update() $context.executeQuery() #Rename Shared Document library Write-host " " Write-host " Modification of the Shared Document lib" -ForegroundColor green $MyList = $context.Web.Lists.GetByTitle("Documents") $context.Load($MyList) $context.executeQuery() $MyList.Title = "Other Documents" $MyList.OnQuickLaunch = $True $MyList.Update() $context.executeQuery() #Create Contact List Write-host " " Write-host " Creation of Contacts list" -ForegroundColor green Create-SPWebList "SubsiteContacts" "Subsite Contacts" 105 $context $MyList = $context.Web.Lists.GetByTitle("SubsiteContacts") $context.Load($MyList) $context.executeQuery() $MyList.Title = "Subsite Contacts" $MyList.EnableAttachments = $false $MyList.EnableFolderCreation = $false $MyList.OnQuickLaunch = $True $MyList.Update() $context.executeQuery() #Create Links List Write-host " " Write-host " Creation of Links list" -ForegroundColor green Create-SPWebList "SubsiteLinks" "Subsite Links" 103 $context $MyList = $context.Web.Lists.GetByTitle("SubsiteLinks") $context.Load($MyList) $context.executeQuery() $MyList.Title = "Subsite Links" $MyList.EnableAttachments = $false $MyList.EnableFolderCreation = $false $MyList.OnQuickLaunch = $false $MyList.Update() $context.executeQuery() #Create Calendar List Write-host " " Write-host " Creation of Calendar list" -ForegroundColor green Create-SPWebList "SubsiteCalendar" "Subsite Calendar" 106 $context $MyList = $context.Web.Lists.GetByTitle("SubsiteCalendar") $context.Load($MyList) $context.executeQuery() $MyList.Title = "Subsite Calendar" $MyList.EnableAttachments = $false $MyList.EnableFolderCreation = $false $MyList.OnQuickLaunch = $True $MyList.Update() $context.executeQuery() Write-host " " Write-host " Start the Navigation Cleanup" -ForegroundColor green $QuickLaunchNodes = $web.Navigation.QuickLaunch $context.Load($QuickLaunchNodes) #send the request containing all operations to the server $context.executeQuery() for($i=$QuickLaunchNodes.Count-1;$i -ge 0; $i--) { write-host " >>> MenuItem $($QuickLaunchNodes[$i].Title) - ID: $($QuickLaunchNodes[$i].Id)" -foregroundcolor green #write-host " >>> MenuItem Children $($QuickLaunchNodes[$i].Children) " -foregroundcolor green switch ($QuickLaunchNodes[$i].Title) { "Home" { $QuickLaunchNodes[$i].DeleteObject() $context.executeQuery() write-host " >>> MenuItem $($QuickLaunchNodes[$i].Title) Link Found !!!!" -foregroundcolor red } "Recent" { $QuickLaunchNodes[$i].DeleteObject() $context.executeQuery() write-host " >>> MenuItem $($QuickLaunchNodes[$i].Title) Link Found !!!!" -foregroundcolor red } "Pages" { $QuickLaunchNodes[$i].DeleteObject() $context.executeQuery() write-host " >>> MenuItem $($QuickLaunchNodes[$i].Title) Link Found !!!!" -foregroundcolor red } "Site contents" { $QuickLaunchNodes[$i].DeleteObject() $context.executeQuery() write-host " >>> MenuItem $($QuickLaunchNodes[$i].Title) Link Found !!!!" -foregroundcolor red } } } Write-host " Add the new Home Link into the Navigation Menu", $SubSiteFullUrl -ForegroundColor green $NavigationNode = New-Object Microsoft.SharePoint.Client.NavigationNodeCreationInformation $NavigationNode.Title = "Subsite Home" $NavigationNode.Url = $SubSiteFullUrl #$NavigationNode.AsLastNode = $true $context.Load($QuickLaunchNodes.Add($NavigationNode)) $context.executeQuery() Write-host " Add the Link into the Subsite Navigation Menu", $SiteIntegrationUrl -ForegroundColor green $QuickLaunchNodes = $Myctx.web.Navigation.QuickLaunch $Myctx.Load($QuickLaunchNodes) $Myctx.executeQuery() $NavigationNode = New-Object Microsoft.SharePoint.Client.NavigationNodeCreationInformation $NavigationNode.Title = $SubSiteName $NavigationNode.Url = $SubSiteFullUrl $NavigationNode.AsLastNode = $true $Myctx.Load($QuickLaunchNodes.Add($NavigationNode)) $Myctx.executeQuery() } else { Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ====>> THE SUBSITE IS YET CREATED:", $SubSiteFullUrl -ForegroundColor red } Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green
---------------------------------------------------------
PnP PowerShell script
The sources used for this second script are:
Feel free to adapt and use it as you need.
if (-not (Get-Module -ListAvailable -Name SharePointPnPPowerShellOnline)) { Install-Module SharePointPnPPowerShellOnline } Import-Module SharePointPnPPowerShellOnline # VALUE TO ADAPT !!!!! # -------------------------------------------------------------------------------------------- $SiteIntegrationUrl ="https://tenant.sharepoint.com/sites/SiteCollection/Subsite1" $SubSiteURL = "testsubsite" $SubSiteName ="_TESTSUBSITE" $EmailAddressAccessRequest = "emailaddresstosupport@domain.com" $RootSiteOwnerGroup = "Root Site Collection Owners" # -------------------------------------------------------------------------------------------- #Custom Function to Check if Site Collection Exists in Given URL Function Check-SiteExists($MySiteURL, $MyCredentials) { Try { Connect-PnPOnline -Url $MySiteURL -Credentials $MyCredentials Return $True } Catch [Exception] { Write-host " >>>> ERROR MESSAGE:", $_.Exception.Message -f Red Return $False } } # --------------------------------------------------------------------------------------------------------------- #get and save your O365 credentials [string]$username = "AdminSiteCollection@tenant.onmicrosoft.com" [string]$PwdTXTPath = "C:\SECUREDPWD\ExportedPWD-$($username).txt" $secureStringPwd = ConvertTo-SecureString -string (Get-Content $PwdTXTPath) $cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd $DocLibTitleLong = "Given Documents" $DocLibTitle = -join($SubSiteURL, "GivenDocuments") $DocLibTitleLong = -join($SubSiteName, " Given Documents") $SubSiteTitle = -join($SubSiteName, " - Subsite Usage") $SubSiteOwnerOwners = -join($SubSiteName, " Subsite Usage Web Owners") $SubSiteOwnerMembers = -join($SubSiteName, " Subsite Usage Web Members") $SubSiteOwnerVisitors = -join($SubSiteName, " Subsite Usage Web Visitors") $siteUrl = -join($SiteIntegrationUrl, "/", $SubSiteURL) # --------------------------------------------------------------------------------------------------------------- #connect to the web site using the stored credentials Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- CONNECT THE SITE --- " -ForegroundColor green Write-host " CONNECTED SITE:", $SiteIntegrationUrl -ForegroundColor Yellow Connect-PnPOnline -Url $SiteIntegrationUrl -Credential $cred Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- START THE SUBSITE CREATION :", $siteUrl -ForegroundColor green Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green $SiteExists = Check-SiteExists $siteUrl $cred if($SiteExists -ne $true) { Write-host " NEW SITE URL TO CREATE:", $siteUrl -ForegroundColor Yellow #Create the subWeb for the Integration site New-PnPWeb -Template "STS#0" -Title $SubSiteTitle -Description $SubSiteTitle -Url $SubSiteURL -Locale "1033" -InheritNavigation -BreakInheritance Add-PnPNavigationNode -Title $SubSiteTitle -Url $siteUrl -Location "QuickLaunch" #connect to the new web site using the stored credentials Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- CONNECT THE SITE --- " -ForegroundColor green Write-host " CONNECTED SITE:", $siteUrl -ForegroundColor green Connect-PnPOnline -Url $siteUrl -Credentials $cred $MyCurrentWeb = Get-PnPWeb #configure the Access request system Set-PnPRequestAccessEmails -Emails $EmailAddressAccessRequest #Create the Doc Lib Write-host " " Write-host " Create Doc Lib:", $DocLibTitle -ForegroundColor green New-PnPList -Title $DocLibTitle -Template DocumentLibrary -OnQuickLaunch Set-PnPList -Identity $DocLibTitle -Title $DocLibTitleLong -EnableVersioning $true -MajorVersions 100 -EnableMinorVersions $false #Rename Shared Document library Write-host " " Write-host " Modification of the Shared Document lib" -ForegroundColor green Set-PnPList -Identity "Documents" -Title "Other Documents" -EnableVersioning $true -MajorVersions 100 -EnableMinorVersions $false #Create Contact List Write-host " " Write-host " Creation of Contacts list" -ForegroundColor green New-PnPList -Title "SubsiteContacts" -Template Contacts -OnQuickLaunch Set-PnPList -Identity "SubsiteContacts" -Title "Subsite Contacts" #Create Links List Write-host " " Write-host " Creation of Links list" -ForegroundColor green New-PnPList -Title "SubsiteLinks" -Template Links Set-PnPList -Identity "SubsiteLinks" -Title "Subsite Links" #Create Calendar List Write-host " " Write-host " Creation of Calendar list" -ForegroundColor green New-PnPList -Title "SubsiteCalendar" -Template "Events" -OnQuickLaunch Set-PnPList -Identity "SubsiteCalendar" -Title "Subsite Calendar" #Change the Navifation menu Write-host " " Write-host " Modification of the Navigation Menu" -ForegroundColor green Remove-PnPNavigationNode -Title "Pages" -Location QuickLaunch -Force Remove-PnPNavigationNode -Title "Recent" -Location QuickLaunch -Force Remove-PnPNavigationNode -Title "Site contents" -Location QuickLaunch -Force Remove-PnPNavigationNode -Title "Home" -Location QuickLaunch -Force Add-PnPNavigationNode -Title "Subsite Home" -Url $siteUrl -Location "QuickLaunch" -First #Configure the permission set by default Write-host " " Write-host " Get the OwnerGroup from the root site", $RootSiteOwnerGroup -ForegroundColor green $owner = Get-PnPGroup -Identity $RootSiteOwnerGroup #(Get-PnPContext).Credentials.UserName Write-host " >>> Group ID:", $owner.ID -ForegroundColor green Set-PnPWebPermission -Identity $MyCurrentWeb.Id -Group $RootSiteOwnerGroup -AddRole "Full Control" #Create default groups for the new web #here, by default owner will be the person provisioning the groups Write-host " " Write-host " Creation of the Owners group", $SubSiteOwnerOwners -ForegroundColor green $ownerGroup = New-PnPGroup -Title $SubSiteOwnerOwners -Owner $RootSiteOwnerGroup Set-PnPGroup -Identity $SubSiteOwnerOwners -SetAssociatedGroup Owners -AddRole "Full Control" Write-host " " Write-host " Creation of the Members group", $SubSiteOwnerOwners -ForegroundColor green $memberGroup = New-PnPGroup -Title $SubSiteOwnerMembers -Owner $RootSiteOwnerGroup Set-PnPGroup -Identity $SubSiteOwnerMembers -SetAssociatedGroup Members -AddRole "Edit" Write-host " " Write-host " Creation of the Visitors group", $SubSiteOwnerOwners -ForegroundColor green $visitorGroup = New-PnPGroup -Title $SubSiteOwnerVisitors -Owner $RootSiteOwnerGroup Set-PnPGroup -Identity $SubSiteOwnerVisitors -SetAssociatedGroup Visitors -AddRole "Read" } else { Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ====>> THE SUBSITE IS YET CREATED:", $siteUrl -ForegroundColor red } Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green Write-host " ---- DISCONNECT THE SITE --- " -ForegroundColor green # Quit the script and disconnect from the site Disconnect-PnPOnline Write-host " " Write-host " -------------------------------------------------------------------------------------------- " -ForegroundColor green
---------------------------------------------------------
As you can see the PnP is smaller than the CSOM, because that solution is based on interface solution. Internally PnP is using the CSOM to work with Office 365, but you have to install it and update it too.
Fabrice Romelard [MVP]
Jun 12 2018 05:58 AM
The French version of that article:
Fab
Oct 08 2018 11:58 PM
Bonjour Fabrice,
I followed the pnp powershell path but I am block with an access denied exception.
Set-PnPGroup -Identity 'Cours - Visiteurs' -SetAssociatedGroup Visitors -AddRole 'Read'
Set-PnPGroup : Access denied. You do not have permission to perform this action or access this resource.
Au caractère Ligne:1 : 9
+ Set-PnPGroup -Identity 'Cours - Visiteurs' -SetAssociatedGrou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Set-PnPGroup], ServerUnauthorizedAccessException
+ FullyQualifiedErrorId : EXCEPTION,SharePointPnP.PowerShell.Commands.Principals.SetGroup
The group exist and I am connected (Connect-PnPOnline) as the tenant administrator who is also the owner of the sub site, the groups, etc. And I am using PnpPowerShellOnline 3.1.1809.0 from the PSGallery.
Do you had / have the same problem ?
Another point, my intent is to put the subsite provisionning in an Azure function. Is it better to use CSOM or PnP for stability reason.
Jean Marie
Oct 09 2018 01:47 AM
Dear Jean-Marie,
The part of the code "SetAssociatedGroup" is always the painful one.
It's mainly related to the modification Microsoft is doing on the SharePoint side (with the modern group sites).
This option is blocking without any real reason and the only way I found to execute it is to unlock the site before the command execution with that command:
- Set-SPOSite [RootSiteCollectionURL] -DenyAddAndCustomizePages 0
I'm really not sure that will help you in that case, but in many one it was the solution to.
Fab
Oct 09 2018 06:06 AM
No more authorization error while setting the default group !!
Thanks for the tip.
I will put the value back for now as I really can't image the side effect of this.