Skip to content

Instantly share code, notes, and snippets.

@xinmyname
Created March 17, 2011 21:00
Show Gist options
  • Save xinmyname/875118 to your computer and use it in GitHub Desktop.
Save xinmyname/875118 to your computer and use it in GitHub Desktop.
WSP Utilities for SharePoint
# Magic fairy dust for working with WSPs and SharePoint 2010 in PowerShell
# So far, I've only tested this with event receivers, but I'll expand it
# as necessary.
function Get-WSPFeatures {
param($wspFilename = $(throw "Please specify a WSP file."))
$wspPath = (gci $wspFilename).FullName
$wsp = _wspExtractWSP $wspPath
_wspGetFeatures $wsp | echo
_wspGetAssemblies $wsp | ft -auto
_wspCloseWSP $wsp
}
function Get-WSPDeployedFeatures {
param($wspName = $(throw "Please specify the name of a WSP."))
$wspName = _wspGetName($wspName)
Get-SPFeature | Where-Object { $_.SolutionId -eq (Get-SPSolution $wspName).Id }
}
function Register-WSP {
param($wspFilename = $(throw "Please specify a WSP file."), $url)
$wspPath = (gci $wspFilename).FullName
$wspName = _wspGetName($wspFilename)
$webAppUrl = _wspGetWebAppUrl($url)
$wsp = _wspExtractWSP $wspPath
_wspGetFeatures $wsp |% {
$feature = $_
$scope = _wspGetFeatureScope $wsp $feature
if ($scope -eq "Web" -and -not $url) {
throw "This WSP has features in Web scope, please specify a URL to deploy these features to."
}
}
Write-Host "Assemblies to be deployed"
_wspGetAssemblies $wsp | ft -auto
Write-Host "Installing solution..."
Add-SPSolution $wspPath | out-null
Install-SPSolution $wspName -GACDeployment -WebApplication $webAppUrl
Write-Host "Waiting for deployment..."
_wspWaitForSolutionDeployment $wspName $true
Write-Host "Enabling features..."
_wspGetFeatures $wsp |% {
$feature = $_
$scope = _wspGetFeatureScope $wsp $feature
Enable-SPFeature $feature -Url $webAppUrl
Write-Host "$feature Enabled"
}
_wspCloseWSP $wsp
Write-Host "Solution added, installed and all features enabled."
}
function Unregister-WSP {
param($wspName = $(throw "Please specify the name of a WSP."), $url)
$wspName = _wspGetname($wspName)
$webAppUrl = _wspGetWebAppUrl($url)
$features = Get-SPFeature | where { $_.SolutionId -eq (Get-SPSolution $wspName).Id }
$features |% {
if ($_.Scope -eq "Web" -and -not $url) {
throw "This WSP has features in Web scope, please specify a URL to deploy these features to."
}
}
Write-Host "Recycling application pools..."
_wspRecycleAppPools $wspName
Write-Host "Disabling features..."
$features |% {
$feature = $_
Disable-SPFeature -Confirm:$false $feature -Url $webAppUrl
$displayName = $feature.DisplayName
Write-Host "$displayName Disabled"
}
if (_wspIsWebApplicationDeployed $wspName) {
Write-Host "Solution is deployed to one or more web applications - uninstalling."
(Get-SPSolution $wspName).DeployedWebApplications | where { $url -match $_.Url } | select Url |% {
$appUrl = $_.Url
Uninstall-SPSolution -Confirm:$false $wspName -WebApplication $appUrl
Write-Host "$appUrl - uninstalled."
}
} elseif (_wspIsGlobalDeployed $wspName) {
Write-Host "Solution is deployed globally - uninstalling."
Uninstall-SPSolution -Confirm:$false $wspName
}
Write-Host "Waiting for retraction..."
_wspWaitForSolutionDeploymentTimer $wspName
Remove-SPSolution -Confirm:$false $wspName
Write-Host "All features disabled, solution uninstalled and removed."
}
function Find-SPFeature($spec) {
if (-not $spec) {
$spec = "*"
}
Get-SPFeature | where { $_.DisplayName -like $spec } |% {
$feature = $_
$solution = Get-SPSolution | where { $_.Id -eq $feature.SolutionId }
if ($solution) {
$solutionName = $solution.Name
$solutionId = $solution.Id
} else {
$solutionName = "(none)"
$solutionId = "(none)"
}
$result = New-Object Object
Add-Member -member NoteProperty -input $result -name FeatureName -Value $_.DisplayName
Add-Member -member NoteProperty -input $result -name FeatureId -Value $_.Id
Add-Member -member NoteProperty -input $result -name SolutionName -Value $solutionName
Add-Member -member NoteProperty -input $result -name SolutionId -Value $solutionId
Add-Member -member NoteProperty -input $result -name Scope -Value $_.Scope
$result
}
}
function _wspExtractWSP($wspPath) {
$wsp = $env:temp+"\"+ [system.guid]::newguid().tostring()
mkdir $wsp | out-null
expand $wspPath -F:* $wsp | out-null
return $wsp
}
function _wspCloseWSP($wsp) {
ri -r -fo $wsp | out-null
}
function _wspWaitForSolutionDeployment($wspName, $state) {
$solution = Get-SPSolution $wspName
do {
Write-Host -NoNewLine "."
Start-Sleep -s 2
} until ($solution.Deployed -eq $state)
Write-Host -NoNewLine "."
Start-Sleep -s 2
Write-Host "."
}
function _wspWaitForSolutionDeploymentTimer($wspName) {
do {
Write-Host -NoNewLine "."
Start-Sleep -s 2
$timerJob = Get-SPTimerJob | where { $_.Name -like "*$wspName*" } | select -first 1
} until (-not $timerJob)
Write-Host ""
}
function _wspGetFeatures($wsp) {
$manifest = $wsp+"\manifest.xml"
$xml = [xml](gc $manifest)
$xml.Solution.FeatureManifests.FeatureManifest |% {
$location = $_.Location
$location.Substring(0, $location.IndexOf("\"))
}
}
function _wspGetAssemblies($wsp) {
$manifest = $wsp+"\manifest.xml"
$xml = [xml](gc $manifest)
$now = Get-Date
$hourOffset = ($now.ToLocalTime() - $now.ToUniversalTime()).Hours
$xml.Solution.Assemblies.Assembly |% {
$location = $_.Location
$target = $_.DeploymentTarget
$assemblyFile = (gci "$wsp\$location")
$assemblyName = $assemblyFile.Name
$assemblyLength = $assemblyFile.Length
$assemblyDate = $assemblyFile.LastWriteTime.AddHours($hourOffset)
$result = New-Object Object
Add-Member -member NoteProperty -input $result -name AssemblyName -Value $assemblyName
Add-Member -member NoteProperty -input $result -name Target -Value $target
Add-Member -member NoteProperty -input $result -name Length -Value $assemblyLength
Add-Member -member NoteProperty -input $result -name Date -Value $assemblyDate
$result
}
}
function _wspGetFeatureScope($wsp, $featureName) {
$feature = "$wsp\$featureName\Feature.xml"
$xml = [xml](gc $feature)
return $xml.Feature.Scope
}
function _wspGetFeatureReceiverUrl($wsp, $featureName) {
$feature = "$wsp\$featureName\Feature.xml"
$xml = [xml](gc $feature)
$xml.Feature.ElementManifests.ElementManifest |% {
$elementManifest = $_
$location = $elementManifest.Location
# TODO: Need to finish this. It will be used to verify a ListUrl exists before deployment
}
}
function _wspGetName($wspName) {
if (test-path $wspName) {
return (gci $wspName).Name
}
return $wspName
}
function _wspGetWebAppUrl($url) {
if ($url) {
return (Get-SPWeb $url).Site.Url
}
return $url
}
function _wspIsWebApplicationDeployed($wspName) {
$state = (Get-SPSolution $wspName).DeploymentState
return ($state -eq "WebApplicationDeployed" -or $state -eq "GlobalAndWebApplicationDeployed")
}
function _wspIsGlobalDeployed($wspName) {
$state = (Get-SPSolution $wspName).DeploymentState
return ($state -eq "GlobalDeployed" -or $state -eq "GlobalAndWebApplicationDeployed")
}
function _wspRecycleAppPools($wspName) {
$appPoolNames = new-object 'System.Collections.Generic.HashSet[string]'
$appPools = @()
$sites = Get-SPSite | where { $_.Owner }
$solution = Get-SPSolution $wspName
$features = Get-SPFeature | where { $_.SolutionId -eq (Get-SPSolution $wspName).Id }
$features |% {
$feature = $_
$sites |% {
$site = $_
$webApp = $site.WebApplication
$appPool = $webApp.ApplicationPool
$site.AllWebs | select Features |% {
$_.Features | where { $_.DefinitionId -eq $feature.Id } |% {
$result = New-Object Object
Add-Member -member NoteProperty -input $result -name ApplicationPool -Value $appPool
Add-Member -member NoteProperty -input $result -name Site -Value $site
if ($appPoolNames.Add($appPoolName)) {
$appPools += $result
}
}
}
}
}
$appPools |% {
$hostName = $_.Site.HostName
$appPool = $_.ApplicationPool
$appPoolName = $_.ApplicationPool.Name
$wmi = [WmiSearcher]"select * from iisapplicationpool"
$wmi.Scope.Path = "\\$hostName\root\microsoftiisv2"
$wmi.Scope.Options.Authentication = 6
$wmi.Get() | where { $_.name.Contains($appPoolName) } |% {
"Recycling $appPoolName..."
$_.recycle()
}
}
}
New-Alias deploy Register-WSP
New-Alias retract Unregister-WSP
New-Alias ff Find-SPFeature
Export-ModuleMember -Function Get-WSPFeatures
Export-ModuleMember -Function Get-WSPDeployedFeatures
Export-ModuleMember -Function Register-WSP
Export-ModuleMember -Function Unregister-WSP
Export-ModuleMember -Function Find-SPFeature
Export-ModuleMember -Alias deploy
Export-ModuleMember -Alias retract
Export-ModuleMember -Alias ff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment