- Azure PowerShell vs. Azure CLI - Wed, Mar 15 2023
- Use Azure Storage for backup - Thu, Feb 23 2023
- Azure Data Studio vs. SQL Server Management (SSMS) - Wed, Feb 8 2023
You probably also understand that we use Windows PowerShell to automate our administrative work and reduce human errors. In this article, I’ll teach you how to manage your SharePoint Online farm programmatically from your administrative workstation by using only Windows PowerShell.
Windows PowerShell and SharePoint Online
Setting up the environment
I trust that you already have a SharePoint Online subscription. Microsoft sells cloud-based SharePoint both as a standalone service and as a component in their Office 365 portfolio.
While we’re on the subject of trust and assumptions, you’ll need to be a global administrator of your SharePoint Online tenant (account) to perform PowerShell–based remote administration.
On your administrative workstation, go ahead and download/install the SharePoint Online Management Shell. Note that your system needs to be running at least Windows PowerShell 3.0; if it doesn’t, then make sure to nab Windows Management Framework 3.0 first.
Next, fire up an administrative PowerShell console session and look at the included cmdlets:
Get-Command -Module Microsoft.Online.SharePoint.PowerShell | Format-Wide -Column 2 Add-SPOUser Connect-SPOService ConvertTo-SPOMigrationTargetedPackage Disconnect-SPOService Get-SPOAppErrors Get-SPOAppInfo Get-SPODeletedSite Get-SPOExternalUser Get-SPOMigrationJobProgress Get-SPOMigrationJobStatus Get-SPOSite Get-SPOSiteGroup Get-SPOTenant Get-SPOTenantLogEntry Get-SPOTenantLogLastAvailableTimeInUtc Get-SPOTenantSyncClientRestriction Get-SPOUser Get-SPOWebTemplate New-SPOMigrationPackage New-SPOSite New-SPOSiteGroup Remove-SPODeletedSite Remove-SPOExternalUser Remove-SPOMigrationJob Remove-SPOSite Remove-SPOSiteGroup Remove-SPOTenantSyncClientRestriction Remove-SPOUser Repair-SPOSite Request-SPOPersonalSite Request-SPOUpgradeEvaluationSite Restore-SPODeletedSite Set-SPOMigrationPackageAzureSource Set-SPOSite Set-SPOSiteGroup Set-SPOTenant Set-SPOTenantSyncClientRestriction Set-SPOUser Submit-SPOMigrationJob Test-SPOSite Upgrade-SPOSite
Okay. So we see that (a) the SharePoint Online module name is honkin’ long, and (b) all the SharePoint Online cmdlets start with the SPO noun prefix. The next thing you’ll notice is that there are far fewer cmdlets for SharePoint Online than for SharePoint on premises. Finally, you’ll see that the SharePoint Online cmdlets are good for site collection management and user/group administration, but they provide us with no visibility at the site/subsite/list/library level. That’s a major disadvantage, in my humble opinion.
Anyway, before we do any remote administration of our SharePoint Online site(s), we need to connect and authenticate to our tenant administration site. We use, appropriately enough, Connect-SPOService:
Connect-SPOService -Url https://timwarnertech-admin.sharepoint.com -Credential tim@timwarnertech.onmicrosoft.com
You’ll be asked to provide your password in a pop-up text box. Please note that you’ll get an error if you try to connect to one of your SharePoint Online sites. Instead, you need the tenant administration site. This URL normally takes the following form:
https://domainname-admin.sharepoint.com
Interacting with your sites
You know how PowerShell works, right? We use Get- cmdlets to retrieve information about objects. In this case, we’ll start by enumerating all site collections within my SharePoint Online tenant with Get-SPOSite:
Get-SPOSite | Select-Object -Property Url Url --- https://timwarnertech.sharepoint.com/ https://timwarnertech.sharepoint.com/portals/community https://timwarnertech.sharepoint.com/portals/hub https://timwarnertech.sharepoint.com/search https://timwarnertech.sharepoint.com/sites/ediscovery https://timwarnertech-my.sharepoint.com/ Get-SPOSite has a -filter parameter that we can use to isolate a particular site collection more quickly: Get-SPOSite -Filter { Url -like '*search*' } Url Owner Storage Quota --- ----- ------------- https://timwarnertech.sharepoint.com/search 1000
Again, you’re correct in noticing that the SharePoint Online module has no built-in provision for inspecting sites, subsites, or lists and libraries. We’ll need to wait on Microsoft for an updated module. Alternatively, you can develop your own custom code to take advantage of the SharePoint client-side object model (CSOM) or its REST interface.
Because I know I have the most content in my top-level site collection, let’s put the object into a variable and see what properties are available:
$site = Get-SPOSite –Identity https://timwarnertech.sharepoint.com $site | Get-Member –MemberType Property | Select-Object –Property Name | Format-Wide –Column 2 AllowSelfServiceUpgrade CompatibilityLevel DenyAddAndCustomizePages DisableSharingForNonOwnersStatus LastContentModifiedDate LocaleId LockIssue LockState Owner PWAEnabled ResourceQuota ResourceQuotaWarningLevel ResourceUsageAverage ResourceUsageCurrent SandboxedCodeActivationCapability SharingCapability Status StorageQuota StorageQuotaWarningLevel StorageUsageCurrent Template Title Url WebsCount
We can now use “dot notation” to retrieve property values. Admittedly, there isn’t a whole lot to look at as of this writing in Summer 2015. As an example, let’s verify the site collection’s status:
$site.Status Active
Well, that was exciting (not!). I wonder what this site collection’s storage quota is?
$site.StorageQuota 1000
The 1000 signifies 1000 megabytes, by the way. Perhaps that’s a bit too big—remember that, in the cloud, we pay based on resource utilization. Let’s use Set-SPOSite to reduce the storage quota to 800 MB and generate a warning when we’ve consumed 700 MB:
Set-SPOSite –Identity $site –StorageQuota 800 –StorageQuotaWarningLevel 700 -NoWait
While we’re at it, we can use Test-SPOSite to run site collection health checks on our site collections, and Repair-SPOSite to fix any errors. My site collection is fine, as you can see below:
Test-SPOSite -Identity https://timwarnertech.sharepoint.com -Verbose | Select-Object -Property PassedCount, FailedWarningCount, FailedErrorCount PassedCount FailedWarningCount FailedErrorCount ----------- ------------------ ---------------- 7 0 0
Creating and removing a new site collection
We’ll finish this tutorial with (somewhat of) a flourish by creating a new site collection programmatically. Here are the properties that we want our new site collection to have:
- Template: wiki
- URL: /sites/wiki
- Storage Quota: 500
- Time Zone: Central
We use Get-SPOWebTemplate to fetch the site collection template IDs:
Get-SPOWebTemplate | Select-Object -Property Name, Title Name Title ---- ----- STS#0 Team Site BLOG#0 Blog BDR#0 Document Center DEV#0 Developer Site OFFILE#1 Records Center EHS#1 Team Site - SharePoint Online configuration BICenterSite#0 Business Intelligence Center SRCHCEN#0 Enterprise Search Center BLANKINTERNETCONTAINER#0 Publishing Portal ENTERWIKI#0 Enterprise Wiki PROJECTSITE#0 Project Site PRODUCTCATALOG#0 Product Catalog COMMUNITY#0 Community Site COMMUNITYPORTAL#0 Community Portal SRCHCENTERLITE#0 Basic Search Center visprus#0 Visio Process Repository
Believe it or not, specifying the time zone is required. According to this blog, my time zone (Central) is option value 11. Let’s code:
New-SPOSite -Url https://timwarnertech.sharepoint.com/sites/wiki -Title "Test Wiki" -Owner "tim@timwarnertech.onmicrosoft.com" -Template "ENTERWIKI#0" -TimeZoneId 11 -StorageQuota 500
The previous command throws an error if you specify http instead of https. Here’s an image of my SharePoint Online web portal, featuring our newly minted site collection:
We created the new wiki site collection programmatically with PowerShell.
When you delete a site collection with Remove-SPOSite, the object actually goes to the Recycle Bin first:
Remove-SPOSite –Identity 'https://timwarnertech.sharepoint.com/sites/wiki'
To remove the object permanently, use Remove-SPODeletedSite:
Remove-SPODeletedSite –Identity 'https://timwarnertech.sharepoint.com/sites/wiki' -Confirm:$false
Be careful of adding the -Confirm:$false flag, especially for destructive actions such as nuking a SharePoint Online site collection.
Remember how we used Connect-SPOService to open the channel between our local computer and our SharePoint Online account? Microsoft gives us Disconnect-SPOService to cleanly close the connection and, more importantly, remove your stored account credentials.
In an interactive PowerShell session, simply closing the window implicitly removes all data from your runspace. However, you might consider adding Disconnect-SPOService to your PowerShell scripts to ensure that your stored credentials can’t be hijacked by malicious code elsewhere.
Closing thoughts
In my opinion, the SharePoint Online PowerShell cmdlets are feature-poor and woefully lacking in documentation. For instance, when you try to get help for the New-SPOSite cmdlet:
Get-Help –Name New-SPOSite –ShowWindow
You see a whole lot of nothing, as demonstrated in the following screenshot:
The SharePoint Online cmdlets have almost non-existent documentation.
The disparity between SharePoint on premises and SharePoint Online PowerShell support is astounding. After all, SharePoint Server 2013 includes more than 600 native cmdlets!
In my view, the SharePoint Online cmdlets are best used as a way to enforce site collection governance. For example, you can script out how you want your SharePoint Online site collections defined.
Although I didn’t have time to go into it here, the SharePoint Online module does give you quite a bit of control over user and group accounts as well. Thanks for reading, and more Power to the Shell!