SharePoint 2010 Powershell deployment scripts

In SharePoint 2010 Powershell is preferred over stsadm to deploy solutions. Powershell is more flexible than traditional stsadm. In one of my recent projects on SharePoint 2010 I used powershell for deployment. I needed to create a new site collection based on Records Center template. The features were scoped at all levels Farm, Web Application, Site and Web. I created two powershell files for the deployment a Framework.ps1 containing all the powershell functions for deployment and another one called Deployment.ps1 which contained the initialization values and referred the  Framework.ps1
Here are the contents of my Framework.ps1 file:


function Create-SiteCollection
{
    param ($Url, $SiteName, $SiteCollectionTemplate,  $OwnerAlias)
    $SiteCollection = Get-SPSite $Url -ErrorAction SilentlyContinue
    if ($SiteCollection -ne $null)
    {
        Write-Warning "Site collection already exists. Deleting site collection $SiteName"
        Remove-SPSite -Identity "$Url" -GradualDelete -Confirm:$False
        Write-Host "Site Collection $SiteName deleted sucessfully" -foregroundcolor Green
    }
    Write-Host "Creating Site Collection $SiteName"
    New-SPSite -Url $Url -Name $SiteName -Template $SiteCollectionTemplate -OwnerAlias $OwnerAlias
    Write-Host "Site Collection $SiteName created sucessfully" -foregroundcolor Green
}

function Deactivate-SPFeature
{
    param ($FeatureID, $SiteUrl, $WebApplicationUrl)
    $Feature = Get-SPFeature -Identity $FeatureID -ErrorAction SilentlyContinue
    $IsActiveFeature
    If ($Feature -eq $null)
    {
        Write-Warning "The specified feature ($FeatureID) was not found."
        return
    }
    If ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Farm)
    {
        $IsActiveFeature = Get-SPFeature -Identity $FeatureID -Farm -ErrorAction SilentlyContinue
        If ($IsActiveFeature -eq $null)
        {
            Write-Warning "The specified feature ($FeatureID) is not activated on the Farm."
            return;
        }
        Write-Host "Deactivating Feature $FeatureID."
        Disable-SPFeature -Identity $FeatureID  -confirm:$false
        Write-Host "Feature  $FeatureID deactivated sucessfully"  -foregroundcolor Green
        return;
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::WebApplication)
    {
        $IsActiveFeature = Get-SPFeature -Identity $FeatureID -WebApplication $WebApplicationUrl -ErrorAction SilentlyContinue
        If ($IsActiveFeature -eq $null)
        {
            Write-Warning "The specified feature ($FeatureID) is not activated in the Web application ($WebApplicationUrl)."
            return;
        }
        Write-Host "Deactivating Feature $FeatureID."
        Disable-SPFeature -Identity $FeatureID -Url $WebApplicationUrl -confirm:$false
        Write-Host "Feature  $FeatureID deactivated sucessfully"  -foregroundcolor Green
        return;
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Site)
    {
        $IsActiveFeature = Get-SPFeature -Identity $FeatureID -Site $SiteUrl -ErrorAction SilentlyContinue
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Web)
    {
        $IsActiveFeature = Get-SPFeature -Identity $FeatureID -Web $SiteUrl -ErrorAction SilentlyContinue
    }
    If ($IsActiveFeature -eq $null)
    {
        Write-Warning "The feature $FeatureID is not activated on the site $SiteUrl"
        return;
    }

    Write-Host "Deactivating Feature $FeatureID."
    Disable-SPFeature -Identity $FeatureID  -Url $SiteUrl -confirm:$false
    Write-Host "Feature  $FeatureID deactivated sucessfully"  -foregroundcolor Green
}

function EnableOrSkip-SPFeature
{
    param ($FeatureID, $SiteUrl)
    $Feature = Get-SPFeature -Identity $FeatureID -ErrorAction SilentlyContinue
    If ($Feature -eq $null)
    {
        Write-Warning "The specified feature ($FeatureID) was not found."
        return
    }
    If ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Farm)
    {
        $Feature = Get-SPFeature -Identity $FeatureID -Farm -ErrorAction SilentlyContinue
        if ($Feature -ne $null)
        {
            Write-Host "Feature  $FeatureID is already activated on the Farm"  -foregroundcolor Green
            return;
        }
        Write-Host "Activating feature $FeatureID"
        Enable-SPFeature -Identity $FeatureID -Confirm:$false 
        Write-Host "Feature $FeatureID activated successfully" -foregroundcolor Green
        return;
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::WebApplication)
    {
        $Feature = Get-SPFeature -Identity $FeatureID -WebApplication $SiteUrl -ErrorAction SilentlyContinue
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Site)
    {
        $Feature = Get-SPFeature -Identity $FeatureID -Site $SiteUrl -ErrorAction SilentlyContinue
    }
    ElseIf ($Feature.Scope -eq [Microsoft.SharePoint.SPFeatureScope]::Web)
    {
        $Feature = Get-SPFeature -Identity $FeatureID -Web $SiteUrl -ErrorAction SilentlyContinue
    } 
    If ($Feature -ne $null)
    {
        Write-Host "Feature  $FeatureID is already activated on the site $SiteUrl" -foregroundcolor Green
        return;
    }
    Write-Host "Activating feature $FeatureID"
    Enable-SPFeature -Identity $FeatureID -Url $SiteUrl  -Confirm:$false 
    Write-Host "Feature $FeatureID activated successfully" -foregroundcolor Green
}

function AddAndDeployGlobally-SPSolution
{
    param ( $SolutionPackageName, $SolutionPath)
    # Check if solution exists.
    $Solution = Get-SPSolution -Identity $SolutionPackageName -ErrorAction SilentlyContinue
    if ($Solution -ne $null)
    {
        RetractAndRemove-SPSolution $SolutionPackageName
    }
    # Add solution
    Write-Host "Adding solution $SolutionPackageName."
    Add-SPSolution -LiteralPath $SolutionPath
    Write-Host "$SolutionPackageName added successfully."  -foregroundcolor Green
    # Deploy solution
    $Solution = Get-SPSolution | ? {($_.Name -eq $SolutionPackageName) -and ($_.Deployed -eq $false)}
    if($Solution -ne $null)
    {
        # Install solution on Farm
        Write-Host "Deploying solution to Farm."
        if($Solution.ContainsWebApplicationResource)   
        {
            Install-SPSolution -Identity $SolutionPackageName -WebApplication $WebApplication -       GACDeployment -Confirm:$false
        }
        else
        {
            Install-SPSolution -Identity $SolutionPackageName -GACDeployment -Confirm:$false
        }
        Restart-SPAdminV4
        while ($Solution.Deployed -eq $false)
        {
            Write-Host -NoNewLine .
            Start-Sleep 2
        }
        Write-Host "$SolutionPackageName deployed successfully to Farm." -foregroundcolor Green   
    }
}

function RetractAndRemove-SPSolution
{
    param ( $SolutionPackageName )
    # Check if solution exists.
    $Solution = Get-SPSolution | ? {($_.Name -eq $SolutionPackageName) -and ($_.Deployed -eq $true)}  -ErrorAction SilentlyContinue
    if ($Solution -ne $null)   
    {   
        Write-Host "Rectracting solution: $SolutionPackageName" 
        if($Solution.ContainsWebApplicationResource)   
        {   
            Uninstall-SPSolution $SolutionPackageName -AllWebApplications -Confirm:$false   
        }   
        else   
        {   
            Uninstall-SPSolution $SolutionPackageName -Confirm:$false   
        }
        Restart-SPAdminV4
        while ($Solution.JobExists)
        {
            Write-Host -NoNewLine .
            Start-Sleep 2
        }
        Write-Host "$SolutionPackageName retracted successfully."  -foregroundcolor Green
        if ($(Get-SPSolution | ? {$_.Name -eq $SolutionPackageName}).Deployed -eq $false)
        {
            Write-Host "Removing solution: $SolutionPackageName" 
            Remove-SPSolution $SolutionPackageName -Confirm:$false
            Write-Host "$SolutionPackageName removed successfully."  -foregroundcolor Green
        }
    } 
}

function Restart-SPAdminV4
{
    Stop-Service SPAdminV4
    Start-SPAdminJob 
    Start-Service SPAdminV4
}
And following are the contents of Deployment.ps1 file. The flow of the deployment is defined in this file.

# Reference the Framework.ps1
. .\Framework.ps1

#Declare variables
$WebApplicationUrl="http://intranet.contoso.com"
$Url="http://intranet.contoso.com/sites/Test"
$OwnerAlias="administrator"
$SiteCollectionTemplate ="OFFILE#1"
$SiteName ="Test"
$WspFolderPath = "C:\Scripts\WSPs"

# Put all features in a variable separated by commas
$FeatureIDs = "ae0bcb0f-1ae6-4179-824e-37a560dd1099", "40794151-743e-4810-a953-7457d121e73d" ,"464a81ce-bd51-4e5a-bc06-946daacba509",  
"1d8bf6d5-05f0-4cec-9925-176617a50dca", "947dfaab-5449-4c98-886c-521b2238a678"

#Load SharePoint Snap In
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

# STEP 1, Create site collection.
Create-SiteCollection $Url $SiteName $SiteCollectionTemplate $OwnerAlias 

# STEP 2, Deactivate  features
foreach ($FeatureID in $FeatureIDs)
{
    Deactivate-SPFeature $FeatureID $Url $WebApplicationUrl
}

# STEP 3, retract and remove solutions
foreach($Filename in Get-ChildItem $WspFolderPath)
{
    $SolutionPackageName = $Filename.Name
    RetractAndRemove-SPSolution $SolutionPackageName
}

# STEP 4, Add and deploy solutions
foreach($Filename in Get-ChildItem $WspFolderPath)
{
    $SolutionPackageName = $Filename.Name
    $SolutionPath = $WspFolderPath +"\"+ $SolutionPackageName
    AddAndDeployGlobally-SPSolution $SolutionPackageName $SolutionPath
}

# STEP 5, Activate features
foreach ($FeatureID in $FeatureIDs)
{
    EnableOrSkip-SPFeature $FeatureID $Url
}

# Remove SharePoint Snap In
Remove-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

The Deployment.ps1 starts with by referencing the Framwork.ps1 file. Note that there is a space between two dots at the begining. After that variables are declared. The name of the web application where a site collection is to be created, path of the WSP files, site template type etc.  The  flow of deployment can be understood by reading the inline comments.
Now comes the actual deployment. Place both the script files in your local folder e.g C:\Scripts and the WSP file in a folder inside Scripts folder e.g; C:\Scripts\WSPs.
Now open SharePoint 2010 Management Shell and move to C directory and then to Scripts folder as shown


Next write .\Deployment.ps1 and press Enter. The deployment should start.
profile for Nadeem Yousuf at SharePoint Stack Exchange, Q&A for SharePoint enthusiasts

+