Created
March 17, 2011 21:00
-
-
Save xinmyname/875118 to your computer and use it in GitHub Desktop.
WSP Utilities for SharePoint
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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