Automated SharePoint 2010 Farm Level Solution Deployment and Retraction Process – Part III – Final Version of PowerShell Script

Article Series Content

This is third part of the article series and it provides the final/full version of PowerShell script built in earliar article to automate the SharePoint 2010 Farm Level Solution deployment/retraction process. If you haven’t read the first and Second parts of this series, I would recommend checking it out here at Part I and Part II.

Here is the final version of PowerShell script. Next article in this series will walk through step by step process of how to use this PowerShell script in real world using batch files to automate the process.

<# 
.DESCRIPTION 
    - Run this script to deploy/retract the farm level solution and activate/deactivate features

.GOAL
 - Build the most generic farm level soution deployment script
 
.ASSUMPTION
 - Batch files, log files, and WSPs exists in same directory during deployment process
 
.MAJOR FEATURES IMPLEMENTED
 - Parameters passed in from the batch file
 - Loading SharePoint PowerShell Plugin - Check if its already been loaded
 - Logging of Powershell script execution transcript, New file gets created for each run
 - Solution Deploy or Retract in single click
 - Waiting for  timer job execution while deploying and retracting solution
 - Nullable $siteFeatureNames and $webFeatureNames parameters to support deployment only option, no activation of features
 - Support Multiple Site and Web Level Features - Site feature and web features are passed in as array paramters
 - Support Activation of features at Multiple Webs - Activate/Deactivate Web Level features on all webs in site collection
 - Check for webapplication level resources to deploy or retract solutions at the web application level or all web application level
 - Prompt the script execution details with different color codes - green for major steps, yellow for detailed info, and red for errors

#>

param (
 [string]$solutionName = "$(Read-Host 'Enter the Solution WSP Name. [e.g. Sample.wsp]')",
 [string]$webAppUrl = "$(Read-Host 'Enter the Web Application URL. [e.g. <a href="http://sp2010vm]'/">http://sp2010vm]'</a>)",
    [string]$siteUrl = "$(Read-Host 'Enter the Site Collection URL. [e.g. <a href="http://sp2010vm/sites/site]'">http://sp2010vm/sites/site]'</a>)",
 [string[]]$siteFeatureNames = $null, #"$(Read-Host 'Enter the Site Level Features. [e.g. @('Feature1', 'Feature2')]')",
 [string[]]$webFeatureNames = $null, #"$(Read-Host 'Enter the Web Level Features. [e.g. @('Feature1', 'Feature2')]')",
    [string]$logFileName = "$(Read-Host 'Enter the Log File Name. [e.g. Sample.log]')",
    [string]$action = "$(Read-Host 'Enter [SD] to deploy solutions or [SR] to retract the solution')"
)

# Defination of main function
function main() {
 # find the current directory
 $currentDirectory = Get-Location
   
 # delete existing logfile
 $logFilePath = "$currentDirectory\$logFileName"
 if (Test-Path $logFilePath)
 {
  Remove-Item $logFilePath
 }
 
 # create new log file and start logging
 Start-Transcript $logFilePath

 # check to ensure Microsoft.SharePoint.PowerShell is loaded
 $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
 if ($snapin -eq $null)
 {
  Write-Host "Loading SharePoint Powershell Snapin"
  Add-PSSnapin "Microsoft.SharePoint.Powershell"
 }
 
 # deploy the solution
 if ($action -eq "SD")
 {
  Write-Host "Step 1 - Add Solution Package: " $solutionName -foregroundcolor Green
  AddSolution
  
  Write-Host "Step 2 - Deploy Solution Package: " $solutionName -foregroundcolor Green
  InstallSolution
  
  Write-Host "Step 3 - Timer Job to deploy the Solution Package" -foregroundcolor Green
  Wait4TimerJob

  Write-Host "Step 4 - Activate Site Collection Level Features" -foregroundcolor Green
  ActivateSiteFeatures
  
  Write-Host "Step 5 - Activate Web Level Features" -foregroundcolor Green
  ActivateWebFeatures
 } 
 
 # retract the solution
 if ($action -eq "SR")
 {
  Write-Host "Step 1 - Deactivate Web Level Features" -foregroundcolor Green
  DeactivateWebFeatures
  
  Write-Host "Step 2 - Deactivate Site Collection Level Features" -foregroundcolor Green
  DeactivateSiteFeatures
  
  Write-Host "Step 3 - Uninstall Solution Package: " $solutionName -foregroundcolor Green
  UnInstallSolution
  
  Write-Host "Step 4 - Timer Job to Retract the Solution Package" -foregroundcolor Green
  Wait4TimerJob
  
  Write-Host "Step 5 - Remove Solution Package: " $solutionName -foregroundcolor Green
  RemoveSolution
 }
 
 # stop the logging
 Stop-Transcript
}

# Add the solution package
# Adds a SharePoint solution package to the farm Solution gallery, It doesn't deploy the uploaded solution yet.
function AddSolution()
{
 $solution = Get-SPSolution | where-object {$_.Name -eq $solutionName}
 if ($solution -eq $null)
 {
  Write-Host "Adding solution package" -foregroundcolor Yellow
  $solutionPath = "$currentDirectory\$solutionName"
  Add-SPSolution -LiteralPath $solutionPath -Confirm:$false
 }
}

# Deploy the solution package 
# Deploys an installed SharePoint solution on all the WFE servers in the farm.
# Deploying solution in the farm installs the feature automatically. It installs all the features
# on each server at the farm, web, site collection, and site level but It doesn't activate them.
# Since it provisions the file on each WFE, it is a timer job.
function InstallSolution()
{
 $solution = Get-SPSolution | where-object {$_.Name -eq $solutionName}
 $solutionId = $solution.Id
 if ($solution -ne $null)
 {
  $solutionDeployed = Get-SPSolution -Identity $solutionId | where-object {$_.Deployed -eq "False"}
  if ($solutionDeployed -eq $null)
  {
   if ( $solution.ContainsWebApplicationResource )
   {
    Write-Host "Deploying solution package to web application: " $webAppUrl -foregroundcolor Yellow
    Install-SPSolution -Identity $solutionName -WebApplication $webAppUrl -GACDeployment -Confirm:$false
   }
   else
   {
    Write-Host "Deploying solution package to all web applications" -foregroundcolor Yellow
    Install-SPSolution -Identity $solutionName -GACDeployment -Confirm:$false
   }
  }
 }
}

# Activate the Site level features
function ActivateSiteFeatures()
{ 
 if ($siteFeatureNames -ne $null)
 {
  $spSite = Get-SPSite $siteUrl  
  foreach($siteFeatureName in $siteFeatureNames)
  {
   Write-Host "Trying to Activate Site Collection Level Feature: " $siteFeatureName -foregroundcolor Yellow
   $siteFeature = Get-SPFeature -site $spSite.url | where-object {$_.displayname -eq $siteFeatureName}
   if ($siteFeature -eq $null)
   {
    Write-Host "Activating Site Level Features at " $spSite.url -foregroundcolor Yellow
    Enable-SPFeature –identity $siteFeatureName -URL $spSite.url -Confirm:$false
   }
  }  
  $spSite.Dispose()
 }
}

# Activate the Web level features
function ActivateWebFeatures()
{
 if ($webFeatureNames -ne $null)
 {
  $spSite = Get-SPSite $siteUrl
 
  #Cycle through all webs in the collection and activate all the features
  foreach($spWeb in $spSite.AllWebs)
  { 
   foreach($webFeatureName in $webFeatureNames)
   {  
    Write-Host "Trying to Activate Web Level Features: " $webFeatureName -foregroundcolor Yellow
    $webFeature = Get-SPFeature -web $spWeb.url | where-object {$_.displayname -eq $webFeatureName} 
    if ($webFeature -eq $null)
    {
     Write-Host "Activating " $webFeatureName " at " $spWeb.url -foregroundcolor Yellow
     Enable-SPFeature –identity $webFeatureName -URL $spWeb.url -Confirm:$false
    }
   }
  }
  
  $spWeb.Dispose()
  $spSite.Dispose()
 }
}

# Deactivate the Web level features
function DeactivateWebFeatures()
{
 if ($webFeatureNames -ne $null)
 {
  $spSite = Get-SPSite $siteUrl
 
  #Cycle through all webs in the collection and deactivate all the features
  foreach($spWeb in $spSite.AllWebs)
  { 
   foreach($webFeatureName in $webFeatureNames)
   {  
    Write-Host "Trying to Deactivate Web Level Features: " $webFeatureName -foregroundcolor Yellow
    $webFeature = Get-SPFeature -web $spWeb.url | where-object {$_.displayname -eq $webFeatureName} 
    if ($webFeature -ne $null)
    {
     Write-Host "Deactivating " $webFeatureName " at " $spWeb.url -foregroundcolor Yellow
     Disable-SPFeature –identity $webFeatureName -URL $spWeb.url -Confirm:$false
    }
   }
  }
  
  $spWeb.Dispose()
  $spSite.Dispose()
 }
}

# Deactivate the Site level features
function DeactivateSiteFeatures()
{
 if ($siteFeatureNames -ne $null)
 {
  $spSite = Get-SPSite $siteUrl
  foreach($siteFeatureName in $siteFeatureNames)
  {
   Write-Host "Trying to Deactivate Site Collection Level Feature: " $siteFeatureName -foregroundcolor Yellow
   $siteFeature = Get-SPFeature -site $spSite.url | where-object {$_.displayname -eq $siteFeatureName}
   if ($siteFeature -ne $null)
   {
    Write-Host "Deactivating Site Level Features at " $spSite.url -foregroundcolor Yellow
    Disable-SPFeature –identity $siteFeatureName -URL $spSite.url -Confirm:$false
   }  
  } 
  $spSite.Dispose()
 }
}

# Retract the solution package
# Retracts a deployed SharePoint solution from the farm entirely for all web application or given web application.
# This step removes files from all the front-end Web server.
# Please note that retracting solution in the farm uninstalls the feature automatically, if it hasn't uninstalled using UnInstall-SPFeature.
# Since it removes the file on each WFE, it is a timer job.
function UnInstallSolution()
{
 $solution = Get-SPSolution | where-object {$_.Name -eq $solutionName}
 $solutionId = $solution.Id
 if ($solution -ne $null)
 {
  $solutionDeployed = Get-SPSolution -Identity $solutionId | where-object {$_.Deployed -eq "True"}
  if ($solutionDeployed -ne $null)   
  { 
   if ( $solution.ContainsWebApplicationResource )
   {
    Write-Host "Retracting solution package from web application: " $webAppUrl -foregroundcolor Yellow
    UnInstall-SPSolution -Identity $solutionName -WebApplication $webAppUrl -Confirm:$false
   }
   else
   {
    Write-Host "Retracting solution package from all web applications" -foregroundcolor Yellow
    UnInstall-SPSolution -Identity $solutionName -Confirm:$false
   }
  }
 }
}

# Remove the solution package
# Deletes a SharePoint solution from a farm solution gallery
function RemoveSolution()
{
 $solution = Get-SPSolution | where-object {$_.Name -eq $solutionName}
 if ($solution -ne $null)
 {
  Write-Host "Deleting the solution package" -foregroundcolor Yellow
  Remove-SPSolution $solutionName -Confirm:$false
 }
}

# Wait for timer job during deploy and retract
function Wait4TimerJob()
{
 $solution = Get-SPSolution | where-object {$_.Name -eq $solutionName}
 if ($solution -ne $null)
 {
  $counter = 1  
  $maximum = 50  
  $sleeptime = 2 
  
  Write-Host "Waiting to finish soultion timer job"
  while( ($solution.JobExists -eq $true ) -and ( $counter -lt $maximum ) )
  {  
   Write-Host "Please wait..."
   sleep $sleeptime 
   $counter++  
  }
  
  Write-Host "Finished the solution timer job"   
 }
}

#Run the Main Function
main

 

Advertisements
This entry was posted in SP2010 Admin PowerShell, SP2010 Dev PowerShell. Bookmark the permalink.