Working with Site Collections
The site collection level is the level
at which all your webs and data live. It can seem a little odd when you
first encounter how webs and site collections are referenced in
SharePoint Central Administration versus the object model in
PowerShell. In PowerShell, a site collection is referred to as an SPSite. In the browser, a web is often referred to as a site, while it is referred to as an SPWeb
in PowerShell. These are important distinctions when you are looking
for that verb-noun pair for the cmdlets you need. Note also that the
objects you will be working with in this section require proper
disposal. If you don’t dispose of your objects, you can wind up with
what developers call a memory leak —
essentially, memory that has been used up by your script but never
released back to the system. If you look in Task Manager and notice the
Windows PowerShell process holding on to too much memory (over 1GB if
it’s not doing anything), then you’re probably suffering from a
disposal issue. To get the memory back to the server, close the
SharePoint Management Shell and open it again.
NOTE The SPSiteAdministration commands Get-SPSiteAdministration and Set-SPSiteAdministration allow administrators who do not have access to the site collection to manage certain elements of it. Use of the SPSite-based commands assumes some degree of access to the site collection.
Let’s start by listing all site collections on
the farm. There are two common methods to do this. If you do not need
to list the Central Administration site collection (see the section
“Working with Web Applications”). As usual, the default formatting for the SPSite object provides only a few items for display. Figure 9 shows the Get-SPSite command in action.
The Get-SPSite command, as well as other Get
commands in SharePoint 2013, will return only 20 items before providing
a warning that the list was limited. These commands limit the number of
objects returned for performance reasons. You will greatly appreciate
the limit functionality of the Get commands the first time someone tries to return hundreds of sites and webs. The Get-SPSite command has an optional -Limit parameter that can be set to a number or to All if you wish to return all items. You will see how to use the -Limit parameter in the following section.
As covered previously, if you want to include
site collections associated with Central Administration, you need to
start with the Get-SPWebApplication command along with the IncludeCentralAdministration parameter. You then need to pipe the results to the Get-SPSite command, as shown in Figure 10.
Using SharePoint 2013, along with some basic
PowerShell commands, you have the flexibility to get just a single site
collection or define parameters for getting a subset of the site
collections.
As with many of the cmdlets described so far, you can get a single site collection by using the -Identity parameter, which accepts a few different types of values. In this case, the -Identity parameter can use wildcards as well as regular expressions (when used in conjunction with the RegEx switch parameter). To get a single site collection, simply pass in the URL as a parameter to the Get-SPSite command, which is piped to the Format-List command, as demonstrated in Figure 11. You can use an asterisk as a wildcard to limit your results to just the site collections that match your string.
FIGURE 11
Don’t forget about using the pipeline to filter your site collections. You can reach for the Where-Object command. The Where-Object command is a PowerShell command that uses a script block to filter objects. You commonly use the $_ reference to the current pipeline object to check a property and decide whether to keep the object or ignore it. Use Get-Help Where-Object to learn more about the Where-Object command. The following example reaches out a little further and retrieves only those site collections that have a single SPWeb object, which is the root web:
Get-SPSite –Limit All | Where-Object {$_.allwebs.Count –eq 1}
Before removing any site collections, let’s look
at the backup and restore options. It’s a good practice to back up a
site in case you realize you really needed it after removing it.
By now you should be able to guess that the command to back up a site is Backup-SPSite.
The site collection backup requires that you identify the site to back
up and the path, including the filename, to save the backup image. This
command by itself will back up only a single site collection. For
example, to back up the portal.contoso.com/teams/IT site collection, you would use the following command:
Backup-SPSite http://portal.contoso.com/teams/IT -path c:\backups\contoso\it\it.bak
While that’s handy, it doesn’t scale very well.
Part of the “power” of PowerShell is its ability to loop through
objects. You saw how easy it is to get a list
of all of your site collections. You also know how to back one up.
Therefore, you may be thinking that you should be able to combine those
two tasks in order to back up all of your site collections. PowerShell provides
exactly that capability. Behold, the “back up all your site collections
in a single script” script:
Get-SPSite | ForEach-Object{$FilePath = "c:\backups\" +
$_.Url.Replace
("http://","").Replace(https://,"").Replace("-","--").
Replace("/","-").Replace
(";","-") + ".bak";
Backup-SPSite –Identity $_.Url -Path $FilePath}
There’s a lot going on there, but when it’s broken down it’s easy to understand. The first cmdlet, Get-SPSite,
gets all the site collections in the farm. The next part walks through
the list of site collections and for each one creates a variable named $FilePath that consists of C:\ backups\
plus the name of the site collection, with the protocol (http:// or
https://) removed and any slashes in the URL replaced with dashes.
Because the URL might legitimately have dashes in it, first you replace
them with two dashes so you can tell them apart. Next you strip out any
colon (:) in case the web app is not on a standard port. Finally, you use your old friend Backup-SPSite to back up the current site collection to the location you just built with $FilePath. So simple, yet so powerful.
You’ve probably already figured out that you would use the Restore-SPSite command to restore the backup. The Restore-SPSite command requires the usual standard -Identity and -Path parameters. For example, to restore the it.bak file, use the following command:
Restore-SPSite http://portal.contoso.com/teams/IT
-path c:\backups\contoso\it\it.bak
Now that you have a backup and know how to
restore the site collection, it is time to finally remove it. To do
that, you use the Remove-SPSite
command. Like other destructive commands, you will be prompted to
confirm the deletion of each site collection you specify. Although the Remove-SPSite command will remove only one site collection, you are free to pass the SPSite object into the Remove-SPSite
command using the PowerShell pipeline. You can now appreciate the fact
that PowerShell prompts you to allow the deletion of each and every
site collection.
Now is also a good time to talk about PowerShell’s wonderful -WhatIf parameter. Well-behaved cmdlets that are potentially destructive in nature support the optional -WhatIf switch parameter, and the Remove-SPSite cmdlet is indeed one of those cmdlets. If you add the -WhatIf parameter to the Remove-SPSite command, the command will not actually remove the site but instead indicate what will happen if you remove the -WhatIf
parameter. Nice touch, isn’t it? It might not make sense if you are
working with a single site, but imagine if you ran this command:
$WebApps = Get-SPWebApplication -IncludeCentralAdministration
Now you have a variable that contains all web
applications. Suppose you later decide to remove all site collections.
That is easy enough:
$WebApps | Get-SPSite | Remove-SPSite
That’s fine until you realize, too late, that you just deleted the Central Administration site collection. With the -WhatIf parameter, you are forewarned about the pain you are about to inflict on yourself. Figure 12
demonstrates how smart administrators can leave work on time and
without being escorted out by security with all their belongings in a
box.
Consider using the -WhatIf
parameter whenever you use a command that might destroy your data. It
will help avert those frantic late-night restores and a fair amount of
swearing.