SharePoint Development Practices and Techniques

  • 11/15/2013

Automating SharePoint administration by using Windows PowerShell scripts

Windows PowerShell scripts can be used to automate SharePoint installation and management. When you are using Windows PowerShell scripts to install SharePoint, it is easy to repeat the installation in exactly the same way. This is very useful when you have to create multiple development environments or multiple servers in a production environment, or when a farm has to be rebuilt after a system failure. Be aware that not all steps of the installation can be scripted by using Windows PowerShell, so you will still have to make sure that all steps are documented as well.

Using Windows PowerShell to manage SharePoint is very useful for repeatable tasks. When you use a saved script every time, the chances of human errors causing serious problems during maintenance decrease. Windows PowerShell can also be used to fully automate maintenance steps. It would, for example, be possible to create a Windows PowerShell script that creates a new site collection. The next step would be to add a couple of parameters and then automatically start the script. You could, for instance, start the script whenever a new project or customer is added to a Customer Relationship Management (CRM) system.

Though it is often convenient to use Windows PowerShell to install or configure SharePoint, in some cases you don’t have a choice because some functionality doesn’t show up in the user interface and can only be configured by using Windows PowerShell. Examples of this are the multitenancy features. The multitenancy features are a set of features that allow SharePoint to work as a hosting platform. They allow for operational service management of SharePoint for one or more divisions, organizations, or companies. Using the multitenancy features allows SharePoint to separate data, features, administration, customizations, and operations. In order to set up multitenancy in an environment, you have to set up site subscriptions, partitioned service applications, tenant administration sites, and (optionally) host header site collections and feature packs. All these features can only be configured by using Windows PowerShell.

If you need to install development environments on a regular basis—for instance, because you are working on different projects, or because you are working on a long-running project and developers are coming and going—it is worthwhile to create a Windows PowerShell script to install a development environment. Even if you would just use Windows PowerShell to configure SharePoint, this will save you a lot of time. It will also make sure that your development environments are always configured in exactly the same way. In addition to the fact that doing a scripted installation is often faster, this approach also allows you to do work on something else while the script is running.

There are two different tools in which you can write and run Windows PowerShell scripts: the Windows PowerShell console window or the Windows PowerShell Integrated Scripting Environment (ISE). To make the Windows PowerShell ISE available on your server, you need to install the Windows PowerShell Integrated Scripting Environment (ISE) Windows feature. You can do this by opening up the Server Manager, clicking Add Features, and selecting the ISE feature.

If you are using the console environment, you can either use the general console environment or the SharePoint 2013 Management Shell. You can access the general console environment by selecting it from the Windows Start menu. If it’s not on the first page, you can get to it from the Windows Start menu by simply starting to type PowerShell. This will give you the option to select one of the available Windows PowerShell tools and consoles.

Don’t pick the 32-bit version (x86); SharePoint is a 64-bit product. You can also go to the Windows Start menu to select the SharePoint 2013 Management Shell. You can find this in the same way as the general console; go to the Start menu, start typing PowerShell, and select the SharePoint 2013 Management Console.

These are effectively the same environment, except for the fact that in the SharePoint Management Shell the Microsoft.SharePoint.PowerShell snap-in has already been loaded. If you are using the standard console, you will have to load the snap-in yourself, by using the following command:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"

You add the -ErrorAction “SilentlyContinue” mainly because the console will throw an error if the snap-in has already been loaded. You can ignore this, so it will look nicer if you hide the error. You can also play it safe and check to see whether the snap-in is already loaded before attempting to load it, by using the following:

$snap = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.PowerShell'}
if ($snap -eq $null) {
  Add-PSSnapin Microsoft.SharePoint.PowerShell
}

If you are creating a larger script, it is probably easier to open up the Windows PowerShell ISE, because this provides a better editing environment. You will have to load the Microsoft.SharePoint.PowerShell snap-in into the ISE as well. You can do this by using exactly the same script used for the console. If you find yourself using the ISE a lot, you can also add the snap-in automatically when the ISE starts, by adding it to the Windows PowerShell profile. The profile is a Windows PowerShell script file that runs every time you start Windows PowerShell. It has a .ps1 extension like any normal Windows PowerShell file, and you can put any valid Windows PowerShell cmdlet in it. The only way in which the profile file differs from a normal script file is in its name and location.

If you want to use the profile, you will first have to figure out whether a profile already exists on the server. You can do this by using the Test-Path cmdlet:

Test-Path $profile

If the profile already exists, the Test-Path cmdlet will return True; if it doesn’t exist, it will return False. You can also just run the $profile cmdlet and use Windows Explorer to browse to the path that it returns. If the file isn’t there, the profile doesn’t exist:

$profile

You can use the New-Item cmdlet to create a profile if one doesn’t already exist. -path $profile passes in the full path, and -type file tells the cmdlet that you are trying to create a file:

New-Item -path $profile -type file

When you open the profile, you will notice that it is completely empty. You can add to it any script that you want to always be executed before you start working on your scripts. This could, for instance, be a command telling Windows PowerShell to always go to a default location:

Set-Location C:\scripts

Or you can add the Microsoft.SharePoint.PowerShell snap-in:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"

Using Windows PowerShell to deploy a custom solution

As a developer, you may also find Windows PowerShell very useful for creating a deployment script that can be used to install your custom solution in a SharePoint environment. This will allow you to distribute your custom solution across test, user acceptance, and production environments a lot more easily. It will mean that administrators don’t have to perform a lot of manual steps and that you as a developer don’t have to describe all these steps in a deployment manual.

When using Windows PowerShell to write a deployment script, you will have to take into account that a previous version of your solution might already be installed in the environment that you are deploying to. This means that you first have to retract and remove the solution before you can install and deploy the solution. Retracting a solution forces SharePoint to delete most of the files it copied during deployment as well as to uninstall features and delete assemblies from the global assembly cache. After you’ve retracted a solution, you can then remove it, which deletes the solution package file from the configuration database.

One thing to be aware of is that SharePoint doesn’t clean up after itself very well when you retract a solution. For instance, SharePoint doesn’t explicitly deactivate features before it retracts the solution that they are deployed in. Because of this, it is a best practice to make sure that you deactivate all features in a solution before retracting the solution. Another thing to keep in mind is that SharePoint doesn’t always delete all files that were deployed using a solution when the solution is retracted. When it doesn’t, this often is for a good reason (for instance, because it could cause errors if the files were to be deleted), but it is something to keep in mind because it can cause quite a bit of cluttering, especially in a development or test environment where solutions are installed and retracted all the time.

You can retract a solution package by using the Uninstall-SPSolution cmdlet. When calling Uninstall-SPSolution, you should pass the -Identity parameter and the -Local parameter in the same manner as when calling Install-SPSolution. You should also pass the -Confirm parameter with a value of $false because failing to do so will cause the cmdlet to prompt the user, which can cause problems if the script is not monitored while it runs. After you’ve retracted the solution, you can then remove it by calling Remove-SPSolution, which instructs SharePoint Foundation to delete the solution package file from the configuration database:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"
$SolutionPackageName = "WingtipDevProject1.wsp"
Uninstall-SPSolution -Identity $SolutionPackageName -Local -Confirm:$false
Remove-SPSolution -Identity $SolutionPackageName -Confirm:$false

These calls to Uninstall-SPSolution and Remove-SPSolution will fail if the solution package isn’t currently installed and deployed. Therefore, it makes sense to add a call to Get-SPSolution and conditional logic to determine whether the solution package is currently installed and deployed before attempting to retract or remove it:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"
$SolutionPackageName = "WingtipDevProject1.wsp"
$solution = Get-SPSolution | where-object {$_.Name -eq $SolutionPackageName}
# check to see if solution package has been installed
if ($solution -ne $null) {
  # check to see if solution package is currently deployed
  if($solution.Deployed -eq $true){
    Uninstall-SPSolution -Identity $SolutionPackageName -Local -Confirm:$false
    Remove-SPSolution -Identity $SolutionPackageName -Confirm:$false
  }
}

Now that you’ve made sure that there’s no old version of your solution installed on the farm, you can add and deploy your solution. Listing 2-1 shows the complete Windows PowerShell script. This script can be used to deploy a solution that cannot be scoped to a web application. Also, the DLL file in this solution will be deployed to the global assembly cache. If a solution can be scoped to a web application, the –AllWebApplications parameter can be used to deploy the solution to all web applications, or the –WebApplication parameter can be used to specify a specific web application that the solution should be deployed to.

Listing 2-1 A Windows PowerShell script to uninstall and install a solution

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"
$solution = Get-SPSolution | where-object {$_.Name -eq $SolutionPackageName}
if ($solution -ne $null) {
  if($solution.Deployed -eq $true){
    Uninstall-SPSolution -Identity $SolutionPackageName -Local -Confirm:$false
  }
  Remove-SPSolution -Identity $SolutionPackageName -Confirm:$false
}
Add-SPSolution -LiteralPath $SolutionPackagePath
Install-SPSolution -Identity $SolutionPackageName -Local -GACDeployment