Friday, June 7, 2013

SharePoint 2013 - PowerShell - How to update image url of web part pages

In SharePoint 2010, it's easy to update all "sub site logo url" and "web part page image url", below is the PowerShell script to update one Web Application.

$ImageUrl = "/_layouts/images/CompanyName/logo.png";

function UpdateSubsiteLogoUrl([string]$webApplicationURL) 

Write-Host "webApplication URL: " $webApplicationURL

$webApp = Get-SPWebApplication $webApplicationURL 
foreach($site in $webApp.Sites) 

Write-Host "site URL: " $site.Url
foreach($CurrentWeb in $site.AllWebs) 

[Boolean]$isContextNull = $false;
[System.Web.HttpContext]$htc = $null;
[System.IO.StringWriter]$sw = $null;
[System.Web.HttpResponse]$resp = $null;
[System.Web.HttpRequest]$req = $null;

Write-Host "CurrentWeb URL: " $CurrentWeb.Url
$CurrentWeb.SiteLogoUrl = $ImageUrl;
$CurrentWeb.Update();

# http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/607f3980-53c0-4007-bb34-9969ed6ea4fc
$web = $CurrentWeb

            if ($null -eq [System.Web.HttpContext]::Current){
                Write-Debug "Setting HttpContext";
                $isContextNull = $true;
                $sw = New-Object System.IO.StringWriter;
                $resp = New-Object System.Web.HttpResponse $sw;
                $req = New-Object System.Web.HttpRequest "", $web.Url, "";
                $htc = New-Object System.Web.HttpContext $req, $resp;
                $htc.Items["HttpHandlerSPWeb"] = $web -as [Microsoft.SharePoint.SPweb];
                [System.Web.HttpContext]::Current = $htc;
                if ($sw -ne $null){
                    $sw.Dispose()
                }
            } else {
                Write-Debug "HttpContext already set" -ForegroundColor Red ;
            }

foreach($list in $web.Lists) 
{
if($list.Title -match "Pages" -and -not $list.Hidden)
{
#Write-Host "list.Title = " $list.Title
foreach ($currentPage in $list.RootFolder.Files)
{
if ($currentPage.Name -match ".aspx")
{
Write-Host "currentPage.ServerRelativeUrl = " $currentPage.ServerRelativeUrl
$CurrentWebPartManager = $currentPage.GetLimitedWebPartManager([System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared);

if ($CurrentWebPartManager -ne $null)
{
$CurrentWebPartManager.WebParts | ForEach-Object {
if ($_.Title -eq "Web Part Page Title Bar")
{
$_.Image = $ImageUrl;
$CurrentWebPartManager.SaveChanges($_);
}
}
}
}
}
}
}

if($isContextNull){
                Write-Debug "Resetting HttpContext";
                [System.Web.HttpContext]::Current = $null;
$isContextNull = $false;
            }
           
            $web.Dispose()

}
$site.Dispose();
}
}

However, it doesn't work for SharePoint 2013.

The "fake" httpcontext trick stopped working in SharePoint 2013. All webparts appear as ErrorWebParts now, so we can't modify the the property of "Web Part Page Title Bar" web parts of web part pages.

We know that for SharePoint 2013 upgrade, the farm system folder "/_layouts/images" is changed to "/_layouts/15/images", so how can we do the changes for all web part pages?

The only solution I found is to abandon all references of "SharePoint farm system folder".  It make sense.  In the future, most of web sites will be hosted in cloud. There is no "system folder" of cloud (for developers and SharePoint administrators).

What I did is quite simple.

1. Create a document library for each web application, say "SharedAssets", in the root site of the root site collection;
2. Grant "read" rights of that document library to all users;
3. Change the image url in PowerShell script.

$ImageUrl = "/SharedImages/logo.png";

4. Update all web applications before upgrading the sites.
5. Done.

This is not just for image files. All css, javascript files, etc. should be stored there if they are previously stored in farm system folder.

Please let me know if you know how to change web part property through PowerShell script in SharePoint 2013, I really appreciate it.

No comments:

Post a Comment