Exploring and Inventorying SharePoint Using PowerShell–Part 4: Finding and Resetting Customized Pages

The scripts we include here can put quite a load on the server while running and can impact your users. You may want to only run these outside of business hours. The scripts are for on premises installs of SharePoint and will not work with Office 365 / SharePoint Online.

Michael T. Smith

April 12, 2016

9 Min Read
Exploring and Inventorying SharePoint Using PowerShell–Part 4: Finding and Resetting Customized Pages

In part 1 of this series we explored using PowerShell to inventory top level SharePoint objects. There we saw how to get lists of farm features, web applications, site collections and sites. In part 2 of this series we explored how to get information out of SharePoint about lists, libraries, files and pages. In part 3 we looked into user and security queries. In this article we will dig into more complex queries to find and reset unghosted / customized pages.

A few reminders before we get started…

See part 1 for the basic security requirements for using PowerShell. These scripts can put quite a load on the server while running and can impact your users. You may want to only run these outside of business hours. The scripts in this article are for on premises installs of SharePoint and will not work with Office 365 / SharePoint Online.

Ghosted and Unghosted Pages

In days of SharePoint 2007 we used two odd terms to describe what we did to SharePoint pages while customizing them using SharePoint Designer, and in spite of Microsoft’s efforts to change them, we still refer to Ghosted and Unghosted pages. Today we should use the terms “Customized” for Un-ghosted pages and “Un-customized” for Ghosted pages.

Customized or Configured?

When a site owner uses the Settings menu or Ribbon options to edit a page in the browser they are doing “safe customization” using what we might just call “configuration”. Everything changed in the browser can be undone in the browser. What if you need to make changes that go beyond what you can do in the browser? You open the site in SharePoint Designer. While many of the changes that you make in SharePoint Designer are similar to the changes that you can make in the browser, there are additional edits you can make that will change the way SharePoint stores and delivers a page.

Un-customized (Ghosted):

  • The page definition is stored on the SharePoint server disk drives or file system.

  • Pages delivered from the file system can be quickly rendered and are cacheable.

  • These pages can often be edited in the browser using the Settings, Edit Page menu or the PAGE ribbons. These edits change the configuration of the page, but not the underlying page definition. In the case of web part pages you can add, configure or remove web parts, but not change the layout of the web part zones. In the case of Wiki pages you configure the text, web parts and number of columns, but cannot change the core page layout HTML.

Customized (Un-ghosted):

  • When a page is customized / un-ghosted it is copied from the file system to the SQL database.

  • Every request for a customized page requires a query of a SQL table adding overhead to each page load.

  • Customized pages might not be usable in the next version of SharePoint.

  • Customized pages may impact site and server performance.

  • Customizations to pages are rarely documented by Site Owners and present a support challenge to the next Site Owner who inherits the site. (Please document your changes!)

  • Customizations to a page may prevent the page from even loading. I.e., you can break pages!

What can be Customized?

The thing that will most complicate the final PowerShell script is the number of places where there are files that can be customized using SharePoint Designer.

  • Files in the SPWeb.Files collection. 

     --Example: /Training/default.aspx

  • Page files in libraries such as Site Pages and Pages. Example: /Training /SitePages/Home.aspx

     --Example: /EnterpriseSearch/Pages/videoresults.aspx

  • .ASPX and .MASTER files found in the “_catalogs” path.

     --Example: /_catalogs/masterpage/seattle.master

     --Example: /Search/_catalogs/masterpage/Display Templates/Search/Item_PowerPoint.html

  • List and library forms such as newform.aspx and editform.aspx.

     --Example: /Lists/Announcements/NewForm.aspx

How to Customize a Page

Pages are typically customized using SharePoint Designer.

  1. Download and install SharePoint Designer. (It’s free!) Download either the 2010 or 2013 version to match your SharePoint installation. Use SPD 2013 for Office 365 and SharePoint 2016.

  2. Launch Designer and open your site.

  3. Open a page for editing and click the Advanced Mode button in the HOME ribbon.

  4. Add one space, one blank line, or make any other edit. (I.e. no real change is even needed.)

  5. Click Save.


You have now Customized / Un-ghosted your page! It will now load just a little bit slower (usually too small to notice), may not upgrade to the next version of SharePoint, or it might not even load.

How to Un-Customize a Page

Deleting your customizations from a page will not re-Ghost or un-Customize a page. You have to reset the page, which can be done using the browser, SharePoint Designer or PowerShell.

Reset a page using a browser:

  1. Go to the site and click Settings (gear), Site Settings.

  2. In the Site Actions section click Reset to Site Definition. (or you could just edit your URL to go to _layouts/15/reghost.aspx – there’s that “ghost” word again!)

   

Enter the URL of the page to reset and click the Reset button.
   

Click OK and the file will be reset and all of the customizations will be lost.

Note that you can also reset all customized pages in the site from this page.

Reset a page using SharePoint Designer:

  1. Open your site in Designer.

  2. In the Navigation area click All Files.

  3. Drill down, find your page and notice the “i” icon that indicates that the page has been customized.

  4. Right-click the page file and click Reset to Site Definition.

   

The file will be reset and a backup copy will be made of the customized file.
   

Reset a page using PowerShell or code:

If you want to reset all of the pages in the site in one step, you can use the RevertAllDocumentContentStreams method of the SPWeb object.

$web = Get-SPWeb "http://yourServer/sites/yourSite/yourSubsite"$web.RevertAllDocumentContentStreams()

To reset a particular page you can use the RevertContentStream method of the SPFile object. Here’s an example for a list form.

$web = Get-SPWeb "http://yourServer/sites/yourSite/yourSubsite"$file = $web.GetFile("http://yourServer/sites/yourSite/yourSubsite/Lists/yourList/newform.aspx") $file.RevertContentStream()

 

Note that unlike most updates to SharePoint objects you don’t need to call .Update() on any object to make this change.

 

$file = $web.GetFile("http:// yourServer/sites/yourSite/yourSubsite /SitePages/home.aspx")$file.RevertContentStream()

 

Find All Customized / Un-Ghosted Pages

Now for the scripts…

The first script is “safe”. It will not change anything. While safe, keep in mind running this script in a production environment may impact performance.

Script Notes:

  • The script can process the entire farm, a single Site Collection or a single site.

  • Each section tests a file’s .CustomizedPageStatus property.

  • Some sections test a file’s file extension. (.Name.EndsWith(".aspx"))

  • The master page catalog is accessed using $web.GetCatalog(116).

  • Each section defines custom columns so we can merge the results into a single output that can be sent to Out-GridView, Select *, Export-CSV, etc.

  • Retrieving the list forms requires an extra step to get the file object.

## Select a source... Uncomment one and only one of the following sources:## For all sites:#Get-SPSite -Limit All | Get-SPWeb -Limit All |## or for a single site collection#Get-SPSite http://yourServer/sites/yourSite | Get-SPWeb -Limit All |## or for a single webGet-SPWeb http://yourServer/sites/yourSite |## process one web at a time...ForEach {  #  # Find all SPWeb level files  #  $_ |   Select -ExpandProperty Files |  Where { $_.Name.EndsWith(".aspx") -AND       $_.CustomizedPageStatus -eq "Customized" } |  Select @{l='Location'; e={'WebFile'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # Find all Catalog files (116 = Master Page Gallery)  #  $_.GetCatalog(116).Items  |  Select -ExpandProperty File |  Where { $_.CustomizedPageStatus -eq "Customized" } |  Select @{l='Location'; e={'MP Gallery'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # Find all library files  #  $LibrariesToCheck = "Site Pages", "Pages"  $_ |  Select -ExpandProperty Lists |  where {$LibrariesToCheck -contains $_.Title} |  Select -ExpandProperty Items |  Select -ExpandProperty File |  Where { $_.Name.EndsWith(".aspx") -AND       $_.CustomizedPageStatus -eq "Customized" } |  Select @{l='Location'; e={'Library'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # File all list forms  #  $w = $_; #save the web object for use in the next pipe  $_.Lists.forms |   foreach {$w.getfile($_.url)} |   Where { $_.CustomizedPageStatus -eq "Customized" } |  Select @{l='Location'; e={'List Form'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy} | # Select a destinationSelect * | Format-Table -AutoSize#Out-GridView#Export-Csv C:testListOfCustomizedPages.CSV

 

Reset All Customized / Un-Ghosted Pages

 

Now for a dangerous script…

The script below could undo thousands of dollars of work done by your graphics designers and consultants. Think long and hard before running it, and if possible, run it on a backup copy of the farm. To play it safe, I have commented out the lines that make changes.

The script below is the same as the one above with an extra line in each section. This line calls the RevertContentStream method on each customized file found.

Notes:

  • DO NOT RUN THIS IF YOU DON’T HAVE A BACKUP OF EVERYTHING! 

  • Be very careful about reverting the files in the Master Page Gallery ($_.GetCatalog(116)) as you have potentially paid someone thousands of dollars to make them. Much of your branding work is done on files in this gallery.

  • The lines that make the changes are commented out in the code below. Uncomment these only after running the script above to determine what is about to be changed.

  • RUN AT YOUR OWN RISK!  (’nuff said?)

The update script:

## Select a source... Uncomment one and only one of the following sources## For all sites:#Get-SPSite -Limit All | Get-SPWeb -Limit All |## or for a single web#Get-SPSite http://maxsp2013wfe/sites/training | Get-SPWeb -Limit All |## or for a single webGet-SPWeb http://maxsp2013wfe/sites/training |## process one web at a time...ForEach {  #  # Find all SPWeb level files  #  $_ |   Select -ExpandProperty Files |  Where { $_.Name.EndsWith(".aspx") -AND       $_.CustomizedPageStatus -eq "Customized" } |  ####### Next line does a "Reset to Site Definition"!  ###foreach {$_.RevertContentStream(); $_} |  Select @{l='Location'; e={'WebFile'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # Find all Catalog files (116 = Master Page Gallery)  #  $_.GetCatalog(116).Items  |  Select -ExpandProperty File |  Where { $_.CustomizedPageStatus -eq "Customized" } |  ####### Next line does a "Reset to Site Definition"!  ###foreach {$_.RevertContentStream(); $_} |  Select @{l='Location'; e={'MP Gallery'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # Find all library files  #  $LibrariesToCheck = "Site Pages", "Pages"  $_ |  Select -ExpandProperty Lists |  where {$LibrariesToCheck -contains $_.Title} |  Select -ExpandProperty Items |  Select -ExpandProperty File |  Where { $_.Name.EndsWith(".aspx") -AND       $_.CustomizedPageStatus -eq "Customized" } |  ####### Next line does a "Reset to Site Definition"!  ###foreach {$_.RevertContentStream(); $_} |  Select @{l='Location'; e={'Library'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy  #  # File all list forms  #  $w = $_;  $_.Lists.forms |   foreach {$w.getfile($_.url)} |   Where { $_.CustomizedPageStatus -eq "Customized" } |  ####### Next line does a "Reset to Site Definition"!  ###foreach {$_.RevertContentStream(); $_} |  Select @{l='Location'; e={'List Form'}}, ServerRelativeUrl,      TimeCreated, TimeLastModified, ModifiedBy } | # Select a destinationSelect * | Format-Table -AutoSize#Out-GridView#Export-Csv C:testListOfCustomizedPages.CSV

 

From Inventory to Content to Security to Pages

 

In this article we explored Customized pages and how to find and reset them. In the next article we will go on the search for web parts! Who is using which RSS Feed web part or the Content Editor web part? We will find them.

 

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like