We had a requirement to list all the web parts present in publishing pages of a site collection. This is the PowerShell script we used to export all web parts. The main thing to notice here is the need for having context information.
param (
[string]$spWebAppUrl
)
$xmlWriter = $null
Add-PSSnapin Microsoft.SharePoint.Powershell | out-null
$currentDir = (Resolve-Path .\).Path
function Ensure-HttpContext([string]$url)
{
$sw = New-Object System.IO.StringWriter
$resp = New-Object System.Web.HttpResponse $sw
$req = New-Object System.Web.HttpRequest "", $url, ""
$htc = New-Object System.Web.HttpContext $req, $resp
[System.Web.HttpContext]::Current = $htc
}
function Ensure-SPContext([string]$url)
{
Ensure-HttpContext $url
if(![System.Web.HttpContext]::Current.Items["HttpHandlerSPWeb"] -or
![System.Web.HttpContext]::Current.Items["HttpHandlerSPSite"])
{
[Microsoft.SharePoint.SPWeb]$web = Get-SPWeb $url
[System.Web.HttpContext]::Current.Items["HttpHandlerSPWeb"] = $web
[System.Web.HttpContext]::Current.Items["HttpHandlerSPSite"] = $web.Site
}
}
function ExportWebPart(
$webpartMgr,
$webpart,
$webpartPath
)
{
if (!(test-path -path $webpartPath)) {new-item -path $webpartPath -itemtype directory | Out-Null}
$fileName = Join-Path -Path $webpartPath -ChildPath "$($webpart.Id).webpart"
$webpartXmlWriter = New-Object System.Xml.XmlTextWriter($fileName,$null)
$webpartXmlWriter.Formatting = [System.Xml.Formatting]::Indented
$webpartMgr.ExportWebpart($webpart, $webpartXmlWriter)
$webpartXmlWriter.Dispose()
}
function ProcessSubWebs(
[string]$str
)
{
[System.Web.HttpContext]::Current = $null
$currentWeb = Get-SPWeb $str
write-host -ForegroundColor DarkYellow "Processing $str"
$webFolder = $currentWeb.ServerRelativeUrl
Ensure-SPContext($str)
if([Microsoft.SharePoint.Publishing.PublishingWeb]::IsPublishingWeb($currentWeb))
{
$xmlWriter.WriteStartElement("web")
$xmlWriter.WriteAttributeString("title", $currentWeb.Title)
$xmlWriter.WriteAttributeString("url", $currentWeb.Url)
$publishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($currentWeb)
$spQuery = New-Object Microsoft.SharePoint.SPQuery
$spQuery.ViewAttributes = "Scope='Recursive'"
$publishingPages = $publishingWeb.GetPublishingPages($spQuery)
$xmlWriter.WriteStartElement("pages")
foreach ($publishingPage in $publishingPages)
{
$xmlWriter.WriteStartElement("page")
$xmlWriter.WriteAttributeString("title", $publishingPage.Title)
$xmlWriter.WriteAttributeString("pagecontent", $publishingPage.ListItem["PublishingPageContent"])
$xmlWriter.WriteAttributeString("absoluteurl", $publishingPage.Uri.AbsoluteUri)
$xmlWriter.WriteAttributeString("pagelayout", $publishingPage.Layout.ServerRelativeUrl)
$wpManager = $currentWeb.GetLimitedWebPartManager($publishingPage.Url, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$webparts = $wpManager.WebParts
$pageFolder = $wpManager.ServerRelativeUrl.Replace('/', '\')
$pagePath = join-path -Path $siteFolder -ChildPath $pageFolder
if($webparts.Count -gt 0)
{
$xmlWriter.WriteStartElement("webparts")
foreach($webpart in $webparts)
{
$type = $webpart.GetType().Name
$xmlWriter.WriteStartElement("webpart")
if ($webpart.ExportMode -ne "None")
{
ExportWebPart $wpManager $webpart $pagePath
}
else
{
$xmlWriter.WriteAttributeString("info", "webpart not exported")
}
if ($webpart.IsClosed)
{
$xmlWriter.WriteAttributeString("IsClosed", "true")
}
$xmlWriter.WriteAttributeString("type", $webpart.GetType().Name)
$xmlWriter.WriteAttributeString("title", $webpart.Title)
$xmlWriter.WriteAttributeString("ID", $webpart.ID)
$xmlWriter.WriteAttributeString("zone", $wpManager.GetZoneID($webpart))
$xmlWriter.WriteAttributeString("index", $webpart.ZoneIndex)
if($type -eq "ContentEditorWebPart")
{
$xmlWriter.WriteAttributeString("content", $webpart.Content.InnerText)
$xmlWriter.WriteAttributeString("contentlink", $webpart.ContentLink)
}
elseif($type -eq "ScriptEditorWebPart")
{
$xmlWriter.WriteAttributeString("content", $webpart.Content)
}
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement();
foreach($sub in $currentWeb.Webs)
{
$xmlWriter.WriteStartElement("webs")
ProcessSubWebs $sub.Url
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
}
else
{
Write-Host -Foregroundcolor Red "$str is not a publishing site"
}
}
$site = get-spsite $spWebAppUrl
if ($site)
{
try
{
$siteFolder = (new-object System.Uri $site.Url).Authority
write-host -ForegroundColor Yellow "Processing site pages..."
$xmlFilePath = join-path -Path $currentDir -childpath "$($siteFolder).xml"
$xmlWriter = New-Object System.Xml.XmlTextWriter($xmlFilePath,$null);
$xmlWriter.Formatting = [System.Xml.Formatting]::Indented
$xmlWriter.WriteStartDocument()
$siteFolder = join-path -path $currentDir -ChildPath $siteFolder
ProcessSubWebs $spWebAppUrl
$xmlWriter.WriteEndDocument()
write-host -ForegroundColor Green $xmlFilePath "saved"
}
catch
{
Write-Host "Error : $($_)"
}
finally
{
if($xmlWriter -ne $null)
{
$xmlWriter.Dispose()
}
}
}