Category: Powershell

Promoting Code and Sites from Development to QA to Production using PowerShell

Below is an example of a way to re-create Sites, Libraries, deploy custom code from a Development environment to QA to Staging and finally Production, in a repeatable manner without having to keep multiple versions of PowerShell scripts. It reduces the possiblity of introducing errors.

It consists on one powershell script (which could call on multiple function scripts), which pulls environment varables from a xml file. you would have a separate xml file for each environment.

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

# use the following the determine location of this script file
$scriptPath = Split-Path -parent $MyInvocation.MyCommand.Path
$deploymentXml = $scriptPath + "\Xml\Deploy.xml"

# now load the deployment configuration data
[xml]$Data = get-content $deploymentXml
$iisRootPath = $Data.Deploy.Settings.IISRootPath
$Url = $Data.Deploy.Settings.Url
$Port = $Data.Deploy.Settings.Port
$AppPoolAccount = $Data.Deploy.Settings.AppPoolAccount
$Owner = $Data.Deploy.Settings.Owner
$WebAppName = $Data.Deploy.Settings.WebAppName
$SiteName = $Data.Deploy.Settings.SiteName
$SiteTemplate = $Data.Deploy.Settings.SiteTemplate

# Below is an example of Creating a Site Collection

if ($Port -ne "80")
{
	$Url = $Url + ":" + $port
}

Write-Host "`n Create Site Collection" -ForegroundColor Blue

New-SPSite $url -Template $SiteTemplate  -Name  $SiteName -OwnerAlias $Owner -Confirm:$false

Here is the sample XML file:

<?xml version="1.0"?>
<Deploy>
  <Settings>
    <IISRootPath>C:\inetpub\wwwroot\wss\VirtualDirectories\</IISRootPath>
    <Url>http://siteurl</Url>
    <Port>80</Port>
    <AppPoolAccount>AD\SVCACCOUNT</AppPoolAccount>
    <Owner>AD\SITEOWNER</Owner>
    <SiteName>Site Name</SiteName>
    <SiteTemplate>BICENTERSITE#0</SiteTemplate>
  </Settings>
</Deploy>

The folder / file stucture for each environment (DEV, QA, PROD etc) would look like this:

Deployment Folder Structure

Where the Code Solution (WSP’s) and other deployment files would be placed in the DeployFiles folder, PowerShell Function scripts in the Functions folder and the configuration Deploy.xml file in the the Xml folder. The Deployment.ps1 script (and any functions) would remain the same for each environment.

Web Config entries using PowerShell

The powershell script and xml below  can be used to make modifications to a Web Applications web config file across all SharePoint Servers.

It can add multiple sections / notes / attributes to the web config file using an XML file as a template to define what needs to be added / changed.

The script first cleans up any existing data in the web config matching an unique identifier that will be recorded for each modification.

Next the XML file is loaded and loops through each section of the xml, checking wither to add a new node (ie like an AppSettings node, or a change to an existing node attribute (ie say the Custom Error mode value).

Finally the changes at applied to the web config file.

Note: Remember to change the location and url variables to your environment and site url.

XML data file:

<?xml version="1.0" encoding="utf-8"?> 
<sections> 
  <section> 
    <skip>false</skip> 
    <path>configuration/system.web/customErrors</path> 
    <modifications> 
      <modification> 
        <type>EnsureAttribute</type> 
        <name>mode</name> 
        <value>Off</value> 
      </modification> 
    </modifications> 
  </section> 
  <section> 
    <skip>false</skip> 
    <path>configuration/appSettings</path> 
    <modifications> 
      <modification> 
        <type>EnsureChildNode</type> 
        <name>add[@key="SomeKeyName"][@value="SomeValueName"]</name> 
        <value>add key="SomeKeyName" value="SomeValueName"</value> 
      </modification> 
    </modifications> 
  </section> 
</sections>

PowerShell Script:


#=================================================================== 
# Web Config Modifications Script 
#=================================================================== 
 
Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction "SilentlyContinue" 
 
#connect to the function library for this script 
$functionLocation = "C:\PowerShell\WebConfigModifications" 
. $functionLocation\Web_Config_Modifications_Functions.ps1 
 
#define the SPWebConfigModification constants 
$modificationOwner = "SomeUniqueIdentifier" 
$EnsureChildNode = 0 
$EnsureAttribute = 1 
 
#get the web configuration modifications xml file 
$webconfigLocation = "C:\PowerShell\WebConfigModifications" 
$webconfigData = $webconfigLocation + "\Web_Config_Modifications.xml" 
 
# get the Web Application for the given Url 
$url = "http://YOUR-WEB-APP-URL" 
$webapp = Get-SPWebApplication $url 
$webapp 
#=============================================================================================================== 
 
#Write-Host "`nCleaning up existing Nodes" 
 
#use this statement below to correct for any errors  
#when initially adding new sections / nodes / attributes  
#etc that may cause exceptions 
#$webapp.WebConfigModifications.Clear() 
 
DeleteSections $webapp $modificationOwner $false 
 
#=============================================================================================================== 
Write-Host "`nAdding Web Config Nodes" 
 
#load the xml data 
[xml]$Data = get-content $webconfigData 
 
foreach ($Section in $Data.Sections.Section) 
{  
    #Ignore sections marked to be skipped 
    if ($Section.Skip -eq "false") 
    { 
        $path = $Section.Path 
        foreach ($modification in $Section.modifications.ChildNodes) 
        { 
            if ($modification.type -eq "EnsureAttribute") 
            { 
                $type = $EnsureAttribute 
                $name = $modification.name 
                  $value =  $modification.value  
                 
                Write-Host "`nChanging $path -> $name to $value" 
            }             
            else 
            { 
                $type = $EnsureChildNode 
                $name = $modification.name 
                $value = "<" + $modification.value + "/>" 
                 
                Write-Host "`nAdding Modifications -> $path : $name, $value" 
            }         
             
            CreateConfigChildNode $modificationOwner $type $path $name $value 
        } 
    } 
} 
 
#=============================================================================================================== 
Write-Host "`nApplying Modifications to the Web.Config"         
$webapp.Update() 
$webapp.Parent.ApplyWebConfigModifications() 
Write-Host "`nCompleted Web.Config Modifications" 
 
#----- END OF FILE  -----# 
 
#----- START of FUNCTION FILE ----# 
 
#=================================================================== 
# Web Config Modifications Script Functions 
#=================================================================== 
 
#=================================================================== 
# function to Create Web Config nodes and or change attributes 
#=================================================================== 
function CreateConfigChildNode($Owner, $Type, $Path, $Name, $Value) 
{ 
    $childNode = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification  
    $childNode.Owner = $Owner 
    $childNode.Path = $Path 
    $childNode.Name = $Name 
    $childNode.Value = $Value 
    $childNode.Type = $Type 
 
    $webapp.WebConfigModifications.Add($childNode) 
} 
 
#=================================================================== 
# function to remove all existing node and changes to attributes matching the Owner name 
#=================================================================== 
function DeleteSections($webapp, $Owner, $removeOnly) 
{ 
    $count =  $webapp.WebConfigModifications.Count 
    $foundNodes = $false 
    for ($i=$count ;$i -gt -1; $i--) 
    { 
        if ($webapp.WebConfigModifications[$i].Owner -eq $Owner) 
        { 
            $foundNodes = $true 
            Write-Host "`n$i" 
            $webapp.WebConfigModifications.Remove($webapp.WebConfigModifications[$i]) 
        } 
    } 
 
    if ($foundNodes -and $removeOnly) 
    { 
        $webapp.Parent.ApplyWebConfigModifications() 
        $webapp.Update() 
    } 
} 
 
#----- END OF FILE  -----#