Forum Discussion
SharePoint Online: Create subsite using PowerShell script based on CSOM or PnP
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:
- First script based on CSOM only
- Second script based on PnP
---------------------------------------------------------
CSOM PowerShell script:
This one is based on many articles I found on Internet associated with my development, so the sources which help me:
- https://www.sharepointappie.nl/webnavigationsettings-csom/
- https://msdn.microsoft.com/fr-fr/library/office/microsoft.sharepoint.client.list.aspx
- https://gist.github.com/azam-a/eba51bfbf922d34e8c87
- https://sharepoint.stackexchange.com/questions/165235/setting-sharepoint-group-as-spgroup-owner-using-powershell
- http://www.sharepointfire.com/2016/01/set-custom-permissions-site-sharepoint-online-powershell/
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:
- https://github.com/SharePoint/PnP-PowerShell
- https://veronicageek.com/office-365/sharepoint-online/create-libraries-folders-upload-documents-using-powershell-pnp/2017/12/
- https://thomasdaly.net/2017/03/06/creating-a-site-template-web-using-pnp-powershell-provisioning/
- https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/new-pnpweb?view=sharepoint-ps
- http://www.sharepointdiary.com/2016/10/sharepoint-online-check-if-site-collection-subsite-exists-powershell-csom.html
- https://sharepoint.stackexchange.com/questions/239489/sharepoint-pnp-powershell-how-to-provision-sub-webs-with-unique-permissions-an
- https://www.c-sharpcorner.com/blogs/allow-access-requests-email-settings-in-sharepoint-site-using-pnp-powershell
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]
4 Replies
- jmThiaBrass Contributor
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.SetGroupThe 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
- FromelardIron Contributor
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
- jmThiaBrass Contributor
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.
- FromelardIron Contributor
The French version of that article:
Fab