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