In the not-too-distant past, I found myself using PowerShell to deploy custom SharePoint solutions but still looking for a way to save a little more time. PowerShell deployed the solutions, but that didn’t disable or enable any of the features within the solution. This was a problem because there were feature receivers that were just chomping at the bit to do some work when the feature was activated, but that event simply wasn’t happening. I didn’t want to write a separate script with hard-coded features to turn off/on, and I didn’t want to go through the process of manually enabling them.
I poked around a bit, thinking I could just use the result of a command like Get-SPSolution to access all of the features in the solution. From there it would be as easy as looping over the results and enabling each one. This turned out to be a very disappointing exercise, since no such specific collection of features turned out to actually exist. After some further testing, I decided to turn to Google to show me the way. I feel like I’m not terrible at searching for answers, however the best thing I could find was a short exchange between two developers on a message board that amounted to something like: question > vague answer > nod/wink > high five > walk away.
So without further ado, I’d like to provide a slightly more fleshed out solution for whoever may find themselves in a similar situation. Below is a script that will install one or more packages to a web application and activate the associated features as it goes. The script takes two arguments: the path where the SharePoint packages are located and the web application where there packages should be installed. The magic is at the end. The script will loop over all of the features that have been installed on the farm and compare the ID of the associated solution to the solution that was just installed. If there’s a match, it will then check the web application that the solution was installed to and disable the feature if it was already present and enabled. Finally, the feature will be enabled.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"
$path = $args[0];
$webApp = $args[1];
function WaitForJobToFinish([string]$SolutionFileName)
{
$JobName = "*solution-deployment*$SolutionFileName*"
$job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
if ($job -eq $null)
{
Write-Host 'Timer job not found'
}
else
{
$JobFullName = $job.Name
Write-Host -NoNewLine "Waiting to finish job $JobFullName"
while ((Get-SPTimerJob $JobFullName) -ne $null)
{
Write-Host -NoNewLine .
Start-Sleep -Seconds 2
}
Write-Host "Finished waiting for job.."
}
}
if($path -ne $null)
{
$files = get-childitem $path -filter *.wsp | Sort-Object -Property CreationTime
foreach ($file in $files) {
write-host "Installing Solution"
$solution = Get-SPSolution $file.Name -ErrorAction SilentlyContinue
if ($solution.ContainsWebApplicationResource) {
Install-SPSolution -Identity $file.Name -GACDeployment -Confirm:$false -Force -WebApplication $webApp
}
else
{
Install-SPSolution -Identity $file.Name -GACDeployment -Confirm:$false -Force
}
Write-Host "Waiting for job to finish"
WaitForJobToFinish($file)
write-host "Solution Installed"
if ($solution.LastOperationResult -eq "DeploymentSucceeded")
{
$farm = get-spfarm
foreach ($feature in $farm.featuredefinitions)
{
if ($feature.solutionid -eq $solution.id -and $feature.scope -eq "Site")
{
$site = get-spsite $webApp
$siteFeature = $site.Features[$feature.id]
write-host "Site Feature: " $siteFeature.id
if ($siteFeature -ne $null)
{
write-host " Deactivating feature: " $feature.displayname
disable-spfeature -identity $feature.id -url $webApp -Confirm:$false
}
write-host " Activating feature: " $feature.displayname
enable-spfeature -identity $feature.id -url $webApp -Confirm:$false
}
}
}
}
}
ICF Ironworks is always on the lookout for experienced professionals who believe in hard work, having fun, and great client service.
Thanks Trey ... This was exactly the requirement that I was trying to fulfill.
Posted by: Varun Rangabhashyam | 01/21/2013 at 04:55 AM