For a project I was working on last month, I needed a way to deploy SharePoint 2010 solutions in a controlled manner.
Thanks to Gary Lapointe I was quickly up to speed to create my first Powershell Script. The script he provided in his post makes it possible to deploy solutions using a xml configuration file. But I needed a script that activates the features as well, so I extended Gary’s script.
solutions.xml
<Solutions>
<Solution Path=”[[Solution1.wsp]]” CASPolicies=”false” GACDeployment=”true”>
<WebApplications>
<WebApplication Url=”[[URL]]:8080″>
<Feature Name=”1116af9b-e3b5-498e-9706-1b67b7b60c43″ Url=”[[URL]]” />
<Feature Name=”2220d8aa-2d25-47bb-8d44-29a45caaa4ce” Url=”[[URL]]” />
<Feature Name=”3330364b-e879-4fee-b103-3c3dd10c0a1c” Url=”[[URL]]” />
<Feature Name=”444a36e0-d249-469a-ba46-4ca7baa10ea6″ Url=”[[URL]]” />
</WebApplication>
</WebApplications>
</Solution>
<Solution Path=”[[Solution2.wsp]]” CASPolicies=”false” GACDeployment=”true”>
<WebApplications>
<WebApplication Url=”[[URL]]”>
<Feature Name=”Feature1″ Url=”[[URL]]” />
</WebApplication>
</WebApplications>
</Solution>
</Solutions>
Deplopy.ps1
$solutionfile = “solutions.xml”
if ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{
Add-PSSnapin Microsoft.SharePoint.PowerShell
}
function Install-Solutions([string]$configFile)
{
if ([string]::IsNullOrEmpty($configFile)) { return }
$solutionsConfig = Get-Content $configFile
if ($solutionsConfig -eq $null) { return }
$solutionsConfig.Solutions.Solution | ForEach-Object {
$_.WebApplications.WebApplication | ForEach-Object {
Write-Host $_.Url
$_.Feature | ForEach-Object {
Write-Host $_.Name
[string]$name = $_.Name
[string]$url = $_.Url
Write-Host Deactivate-Feature $name $url
Deactivate-Feature $name $url
}
}
[string]$path = $_.Path
[bool]$gac = [bool]::Parse($_.GACDeployment)
[bool]$cas = [bool]::Parse($_.CASPolicies)
$webApps = $_.WebApplications.WebApplication
Write-Host Install-Solution $path $gac $cas $webApps.Url
Install-Solution $path $gac $cas $webApps.Url
$_.WebApplications.WebApplication | ForEach-Object {
$_.Feature | ForEach-Object {
[string]$name = $_.Name
[string]$url = $_.Url
Activate-Feature $name $url
}
}
}
}
function Deactivate-Feature([string]$featurename, [string]$url)
{
#Check for Sitecollection-scoped feature
$feature = Get-SPFeature $featurename -Site $url -ErrorAction SilentlyContinue
if ($feature -eq $null) {
#Check for Web-scoped feature
$feature = Get-SPFeature $featurename -Web $url -ErrorAction SilentlyContinue
}
if ($feature -ne $null) {
Write-Host Disable-SPFeature -Identity $featurename -Url $url
Disable-SPFeature -Identity $featurename -Url $url -Confirm:$false
}
}
function Activate-Feature([string]$featurename, [string]$url)
{
$feature = Get-SPFeature $featurename -ErrorAction SilentlyContinue
if ($feature -ne $null) {
Write-Host Enable-SPFeature -Identity $featurename -Url $url
Enable-SPFeature -Identity $featurename -Url $url
}
}
function Install-Solution([string]$path, [bool]$gac, [bool]$cas, [string[]]$webApps = @())
{
$spAdminServiceName = “SPAdminV4″
[string]$name = Split-Path -Path $path -Leaf
$solution = Get-SPSolution $name -ErrorAction SilentlyContinue
if ($solution -ne $null) {
#Retract the solution
if ($solution.Deployed) {
Write-Host “Retracting solution $name…”
if ($solution.ContainsWebApplicationResource) {
$solution | Uninstall-SPSolution -AllWebApplications -Confirm:$false
} else {
$solution | Uninstall-SPSolution -Confirm:$false
}
Stop-Service -Name $spAdminServiceName
Start-SPAdminJob -Verbose
Start-Service -Name $spAdminServiceName
#Block until we’re sure the solution is no longer deployed.
do { Start-Sleep 2 } while ((Get-SPSolution $name).Deployed)
}
#Delete the solution
Write-Host “Removing solution $name…”
Get-SPSolution $name | Remove-SPSolution -Confirm:$false
}
#Add the solution
Write-Host “Adding solution $name…”
$solution = Add-SPSolution $path
#Deploy the solution
if (!$solution.ContainsWebApplicationResource) {
Write-Host “Deploying solution $name to the Farm…”
$solution | Install-SPSolution -GACDeployment:$gac -CASPolicies:$cas -Confirm:$false
} else {
if ($webApps -eq $null -or $webApps.Length -eq 0) {
Write-Warning “The solution $name contains web application resources but no web applications were specified to deploy to.”
return
}
$webApps | ForEach-Object {
Write-Host “Deploying solution $name to $_…”
$solution | Install-SPSolution -GACDeployment:$gac -CASPolicies:$cas -WebApplication $_ -Confirm:$false
}
}
Stop-Service -Name $spAdminServiceName
Start-SPAdminJob -Verbose
Start-Service -Name $spAdminServiceName
#Block until we’re sure the solution is deployed.
do { Start-Sleep 2 } while (!((Get-SPSolution $name).Deployed))
}
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
Install-Solutions($solutionfile);