Create and Manage SharePoint Online Sites by Using PowerShell

Create and Manage SharePoint Online Sites by Using PowerShell

  • Comments 13
  • Likes

Summary: Guest blogger, Corey Roth, talks about using Windows PowerShell to create and manage SharePoint online sites.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have a guest post by SharePoint MVP, Corey Roth. Corey will be presenting at TechEd 2014 this year in Houston, and he has taken the time to share his thoughts with us today. Here is a little bit about Corey:

Corey Roth is an independent SharePoint consultant specializing in solutions in the Oil and Gas industry. Corey is a four-time recipient of the Microsoft MVP award in SharePoint Server. He has always focused on rapid adoption of new Microsoft technologies, including SharePoint 2013, Office 365, and Visual Studio 2013. When it comes to SharePoint, he specializes in ECM, Enterprise Search, and Apps. As an active member of the SharePoint community, he often speaks at conferences, events, and user groups. In his blog, Dot Net Mafia, he posts about the latest technology and SharePoint. Corey is a member on the board for the Houston SharePoint Users Group. He has also recently founded an App development company called SP2, specializing in apps for SharePoint 2013. 

     Note  All scripts from today's post are available in the Script Center Repository:

The SharePoint Online Management Shell has been out for a while now, allowing you to script some tasks with your Office 365 deployment. It lets you use Windows PowerShell to create site collections, work with users and groups, and upgrade site collections in SharePoint Online. However, if you are used to working with Windows PowerShell for SharePoint 2013 on-premises, you will notice that a number of common tasks are missing such as creating sites or enabling features.

Luckily, we can make use of the Client Script Object Model (CSOM) in Windows PowerShell to accomplish some of these tasks. Today, we're going to look at creating sites, deleting sites, and getting a list of sites in SharePoint Online. It takes a few more lines of script, but this post will get you started.

Getting started

To work with CSOM in SharePoint Online, we need access to the client assemblies. You can either download the SharePoint Server 2013 Client Components SDK, or you can get the assemblies from a local SharePoint 2013 installation. You don't need to run your Windows PowerShell script on a SharePoint server. It will work from Windows 7 with SP1 or later.

After you have located the assemblies, we need to load them in our script. We can do this a number of ways. If you are working directly on your SharePoint server, you can use LoadWithPartialName:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")

However, if you copied the assemblies manually somewhere, you might want to use Add-Type:

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.dll"

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.Runtime.dll"

We'll add these types to all of our scripts today.

Authentication

After referencing our assemblies, we need to authenticate to SharePoint Online and get a ClientContext object. We use similar command when working with the Managed Client Object Model for SharePoint.

First, store the path to the site collection we want to work with, in addition to the user name. Be sure to  specify a user name that has permission to create sites. If you prefer, you could request all of these variables as parameters to your script.

$siteUrl = “https://mytenant.sharepoint.com/sites/mysitecollection”

$username = "admin@mytenant.onmicrosoft.com"

Now, we need to read the password. The easiest way to do this is with Read-Host and the AsSecureString parameter. When you run the script, you will be prompted to type the password.

$password = Read-Host -Prompt "Enter password" -AsSecureString

We have everything we need to get a ClientContext now. Initialize a new one by using New-Object and pass it to $siteUrl. We’ll name ours $ctx.

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

Then we need to add the credentials by using the SharePointOnlineCredentials object, and pass $username and $password as parameters.  Then, we assign $credentials to the ClientContext object.

$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)

$ctx.Credentials = $credentials

At this point, we can use our ClientContext object to create, delete, and retrieve a list of sites. We’ll use the previous lines in all of our scripts.

Creating sites

In our first example, we’ll start with a script to create a site. The beginning of the script will contain the assembly references and authentication script we showed above. When creating a site, we use the WebCreationInformation object.

In the following script, I specify a relative URL to the site collection and a title. The WebTemplate parameter takes any supported web template in SharePoint Online. You can get a list of these by using SharePoint Online Management Shell and the Get-SPOWebTemplate cmdlet. In the following example, I am using the Team Site template, which is STS#0.

$webCreationInformation = New-Object Microsoft.SharePoint.Client.WebCreationInformation

$webCreationInformation.Url = "site1"

$webCreationInformation.Title = "Site 1"

$webCreationInformation.WebTemplate = "STS#0"

$newWeb = $ctx.Web.Webs.Add($webCreationInformation)

We then pass the WebCreationInformation object to the Webs collection, which we find on our ClientContext.Web object.

If you have used the Client Object Model before, you know you aren’t done yet. You need to call ClientContext.Load() with $newWeb. We follow this with ClientContext.ExecuteQuery().

$ctx.Load($newWeb)

$ctx.ExecuteQuery()

This will send the request to SharePoint and your site will be created.  Running the script won’t yield any output.

Image of website

You might be tempted to add a $newWeb statement after the script executes. However, this will give you the following error message:

format-default : The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

That’s because, the Web object contains a number of collections that also need to be loaded explicitly by using ClientContext.Load. However, you can request properties such as the Title or Url.

Write-Host "Title" $newWeb.Title

Complete script

Here is what the entire script looks like to create a site in SharePoint Online:

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.dll"

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.Runtime.dll"

 

$siteUrl = “https://mytenant.sharepoint.com/sites/mysitecollection”

$username = "admin@mytenant.onmicrosoft.com"

$password = Read-Host -Prompt "Enter password" -AsSecureString

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)

$ctx.Credentials = $credentials

 

$webCreationInformation = New-Object Microsoft.SharePoint.Client.WebCreationInformation

$webCreationInformation.Url = "site1"

$webCreationInformation.Title = "Site 1"

$webCreationInformation.WebTemplate = "STS#0"

$newWeb = $ctx.Web.Webs.Add($webCreationInformation)

 

$ctx.Load($newWeb)

$ctx.ExecuteQuery()

$newWeb

Write-Host "Title" $newWeb.Title

Deleting sites

To delete a site, the process is fairly similar. Instead of setting the ClientContext URL to the site collection, set it to the site that you want to delete:

$siteUrl = “https://mytenant.sharepoint.com/sites/sitecollection/site1”

After we add the script for the references and authentication, get a reference to ClientContex.Web, load it, and call ExecuteQuery().

$web = $ctx.Web

$ctx.Load($web)

$ctx.ExecuteQuery()

Finally, call the Web.DeleteObject method to delete the site. This will require an additional call to ExecuteQuery to finalize the deletion.

$web.DeleteObject()

$ctx.ExecuteQuery()

At this point, the site has been deleted.

Complete script

Here is the complete script for deleting a site in SharePoint Online:

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.dll"

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.Runtime.dll"

 

$siteUrl = “https://mytenant.sharepoint.com/sites/mysitecollection/site1”

$password = Read-Host -Prompt "Enter password" -AsSecureString

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("admin@mytenant.onmicrosoft.com", $password)

$ctx.Credentials = $credentials

 

$web = $ctx.Web

 

$ctx.Load($web)

$ctx.ExecuteQuery()

 

$web.DeleteObject()

$ctx.ExecuteQuery()

Write-Host $web.Title "Site Deleted"

Getting a list of sites

Retrieving a list of sites is a bit more complicated, because of the load requirements around the Web object. Chris O'Brien's post, Using CSOM in PowerShell scripts with Office 365, pointed me in the right direction to make this work. In this script, we’ll return all subsites of the site collection in SharePoint Online. We’ll start the script by using the same script as before to add references and authentication.

Start by getting a reference to the root web of the site collection:

$rootWeb = $ctx.Web

Next, we use the Webs property of the Web object to get the list of all subsites. We then need to load both these objects and call ClientContext.ExecuteQuery().

$ctx.Load($rootWeb)

$ctx.Load($sites)

$ctx.ExecuteQuery()

Unfortunately, you can’t simply call $sites to see a nice list. You need to iterate through each subsite and use ClientContext.Load and ClientContext.ExecuteQuery() to populate the values. That means the script makes a round-trip to the server once for each site, which is not exactly efficient. Here’s how we iterate through the sites and write out the Title and Url properties:

foreach($site in $sites)

{

  $ctx.Load($site)

  $ctx.ExecuteQuery()

 

  Write-Host $site.Title "-" $site.Url

}

The script looks like this when executed:

Image of command output

You’ll notice this returns all subsites including those used by apps. That’s why you see Yammer in the list. You could write additional script to filter that, if desired.

Complete script

Here is the complete script to get all sites in a site collection from SharePoint Online:

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.dll"

Add-Type -Path "c:\folder\Microsoft.SharePoint.Client.Runtime.dll"

 

$siteUrl = "https://mytenant.sharepoint.com/sites/mysitecollection"

$password = Read-Host -Prompt "Enter password" -AsSecureString

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("admin@mytenant.onmicrosoft.com", $password)

$ctx.Credentials = $credentials

 

$rootWeb = $ctx.Web

$sites = $rootWeb.Webs

 

$ctx.Load($rootWeb)

$ctx.Load($sites)

$ctx.ExecuteQuery()

 

foreach($site in $sites)

{

  $ctx.Load($site)

  $ctx.ExecuteQuery()

 

  Write-Host $site.Title "-" $site.Url

}

By using the Client Script Object Model, you can automate more tasks in SharePoint Online. If you are going to be at TechEd North America this year, be sure to check out my session, Windows PowerShell 3.0 Administration with Microsoft SharePoint 2013 and SharePoint Online (OFC-B328). We’ll cover this example and more for SharePoint Online and SharePoint on-premises.

~Corey

Note  Corey has also agreed to be a special guest at the Scripting Guys booth at TechEd. So that will be a great time to meet with Corey and to have all your Windows PowerShell and SharePoint questions answered. WooHoo!

Thank you, Corey, for sharing this. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Nice article and thanks for sharing your knowledge. I really appropriate your views. If you find same related blog or https://www.officeclip.com/">online contact management just visit today.

  • Thanks for the handy demonstration. I'm very delighted to learn how to create and manage sharepoint online site by using PowerShell. It's truly an educative read for me. Glad to be here... http://www.reviewwebhosting.org

  • Hello Scripting Guy, I've got the that feedback if I try to execute the script:

    "Write-Host "Title" $newWeb.Title
    format-default : The collection has not been initialized. It has not been requested or the request has not been executed. It may need
    to be explicitly requested.
    + CategoryInfo : NotSpecified: (:) [format-default], CollectionNotInitializedException
    + FullyQualifiedErrorId : Microsoft.SharePoint.Client.CollectionNotInitializedException,Microsoft.PowerShell.Commands.FormatDefaul
    tCommand"

    What I have to do to initialize the collection?

  • Hello Scripting Guy, I've got the that feedback if I try to execute the script:

    "Write-Host "Title" $newWeb.Title
    format-default : The collection has not been initialized. It has not been requested or the request has not been executed. It may need
    to be explicitly requested.
    + CategoryInfo : NotSpecified: (:) [format-default], CollectionNotInitializedException
    + FullyQualifiedErrorId : Microsoft.SharePoint.Client.CollectionNotInitializedException,Microsoft.PowerShell.Commands.FormatDefaul
    tCommand"

    What I have to do to initialize the collection?

  • Steven -
    Connect-SPOService -Url https://contoso-admin.sharepoint.com -credential admin@contoso.com

    http://technet.microsoft.com/en-us/library/fp161392(v=office.15).aspx

    Regards,
    AR.

  • Steven -
    Connect-SPOService -Url https://contoso-admin.sharepoint.com -credential admin@contoso.com

    http://technet.microsoft.com/en-us/library/fp161392(v=office.15).aspx

    Regards,
    AR.

  • Thanks for this. I was thinking we had been very short changed on the Powershell Cmd-Lets for Sharepoint Online, but this looks like it will overcome a lot of what is missing.

    One Question: - If we want to create a site based on a custom template rather than a standard one, how do we go about that? I have manually created a site from a custom template, but when I examine it to see the template it was created from it reports the built in template that the custom template was derived from, not the custom template itself.

  • Awesome script. What I was wondering about, if you create a site with this script and you want to give it unique permissions, how to create groups for it so that when a user wants to add members they see it in the quick links on the left top corner as associated groups?

  • Is there a way to convert a PowerShell credential object as returned by Get-Credential into a Microsoft.SharePoint.Client.SharePointOnlineCredentials?

    I want to pass the credentials to my script but I have a PS credential. I don't have the username and password at the time the script is called.

    ~Randy

  • Is there a way to make the "list of sites" script and make it recursive so that it lists all sites and subsites? currently it only lists sites directly off the site collection root, but not any nested sites. This would be really helpful. Thank you.

  • awesome post, thanks.