SharePoint Online requires use of the Client Object model when modifying the site via PowerShell due to there being no backend server exposed in Office 365. Users with previous experience of using JavaScript Client Object model will find this a familiar method.
In the example below, the Powershell iterates through all subsites (and subsites of subsites) in a site collection or root site. This could be used for disabling a web scoped feature or automating site modification.
First of all, the variables are initiated including the path to the relevant DLLs.
#connection variables and reference DLL $username = "user@onmicrosoft.com" $password = "Password123" $SiteCollectionUrl = "https://tonyishere.sharepoint.com" Add-Type -Path "c:\Microsoft.SharePoint.Client.dll"
A new object for the client context requires creating, this can be done in a reusable function as shown below.
# Generate ClientContext function so we can reuse function GetClientContext($SiteCollectionUrl, $username, $password) { $securePassword = ConvertTo-SecureString $password -AsPlainText -Force $context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteCollectionUrl) $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) $context.Credentials = $credentials return $context }
The following function has a nested call to call itself, this enables it to iterate through subsites of subsites. Without the nested function call, it would only cover a single subsite depth. The function writes the url of the site to the screen but this could be replaced with more complex functionality such as enabling a feature or creating a list item.
# function to loop through subsites function catchsubsites ($subsiteurl){ $clientContext = GetClientContext $subsiteurl $username $password $rootWeb = $clientContext.Web $childWebs = $rootWeb.Webs $clientContext.Load($rootWeb) $clientContext.Load($childWebs) $clientContext.ExecuteQuery() #do something on top level site write-host $rootWeb.url -ForegroundColor Yellow foreach ($childWeb in $childWebs) { #do something for each subsite write-host $childWeb.url -ForegroundColor Yellow #see if there are any subsites beneath this and loop all of them too catchsubsites $childWeb.url } }
Finally the function is called to kick off the whole process of looping through the site.
#Finally run the function to get it all started! catchsubsites $SiteCollectionUrl
This example could be refined so that it doesn’t authenticate at every request but it does show how simple it can be to create the complex PowerShell scripts that we are all used to using on SharePoint on-premises in the cloud version of Microsoft’s Office 365 SharePoint Online.
Update: Code updated 01/10/2016, fixed variable in loop and added section to run code for parent site
It is working fine but the catchsubsites multiple times rather than the perfect result .. Example
Site 1 — Site Coll
SubSite1
ChildSite1
but the output is coming as
SubSite1
ChildSite1
SubSite1
ChildSite1
SubSite1
ChildSite1
Hi Sarwa,
Thank you for your comment.
The code will dig straight into the child webs so you should get the subsites listed first. The code will list all the subsites that exist in the site collection. If you need them listed in a particular order you could put them into an array and sort them (as this method will always retrieve the subsites first).
This code was designed to loop through each site and do a job (e.g. such as activate a feature) rather than show the list of the sites in a particular order.
I did notice a mistake in the code which i will update now (should have been $childWebs rather than $subWebs in the loop).
Pingback: Set Offline Client Availability To No to Hide Sync for Sites via PowerShell in SharePoint Online | Drew Madelung
can i get the same result with the help of ECMA script or JSOM or SPServices,
i am stuck at the main parent site’s context!
am unable to get the context of subsites when i tried to loop through the subsites.
Yes, you should be able to get the same results using JSOM or REST. It would be pretty intensive to do this look client-side if you had lots of subsites though. I would recommend looking at the REST API to do this through JavaScript.
Something like this would return subsites and you would have to re-loop this for each subsite to get the whole structure:
/_api/web/webinfos?$select=ServerRelativeUrl,Title