Are your SharePoint pages loading slowly because you have numerous closed web parts eating up valuable resources? Are you an admin tasked with tracking down those closed web parts? Recently my friend Brian Gough asked me a fairly simple question: “Is it possible to use PowerShell to find all ‘closed’ webparts in a site collection?” In this post I’ll show you a short PowerShell script that will identify all closed web parts on a site and it’s sub-sites.
Solution
The script below uses an advanced function (requires PowerShell V2) to search within a SharePoint and it’s sub-sites for all instances of closed web parts on all pages. I use the SPLimitedWebPartManager associated with each page within the SPWeb object to get a reference to the web parts. Since I am using the SharePoint API (loaded in the Begin block) directly you can run this against both SharePoint 2007 and 2010 (Note: only tested against SharePoint 2007 so far). If you are running PowerShell V1 you can run just the code inside the function by itself and provide a site URL manually.
Click here to download the script.
function Search-SPClosedWebParts
{
<#
.Synopsis
Finds instances of closed web parts on SharePoint site and sub-sites.
.Description
Finds instances of closed web parts on SharePoint site and sub-sites.
.Parameter
SiteUrl
SiteUrl to search for closed web parts
.Example
Search-SPClosedWebParts
Finds instances of closed web parts on SharePoint site and sub-sites.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, valueFromPipeline=$true)]
[String]
$SiteUrl
)#end param
Begin
{
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
}
Process
{
$site = new-Object Microsoft.SharePoint.SPSite($SiteUrl)
$site.AllWebs | ForEach-Object {
$currentWeb = $_
$pages = $currentWeb.Files | Where-Object {$_.Name -match ".aspx"}
$pages | ForEach-Object {
$currentPage = $_
$webPartManager = $currentWeb.GetLimitedWebPartManager($currentPage.ServerRelativeUrl, `
[System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$webPartManager.WebParts | ForEach-Object {
if($_.IsClosed)
{
Write-Host "'$($_.Title)' on $($currentPage.ServerRelativeUrl) is closed"
}
}
}
$currentWeb.Dispose()
}
$site.Dispose()
}
} #end Search-SPClosedWebParts
$siteUrlToSearch = Read-Host -Prompt "Enter site URL to check for closed web parts"
Search-SPClosedWebParts -SiteUrl $siteUrlToSearch
Screenshot output from calling script
Conclusion
Using the SharePoint API and some basic looping structures I demonstrated a short script that can quickly and easily identify web parts that have been closed. If desired you could modify the script to also automatically delete these closed web parts. Since we are only concerned with finding instances of closed web parts I have left that functionality out for now. Feel free to use and adapt this script as you like, but please attribute the original source if you re-publish or distribute a modified version. Now go enjoy all that extra time you’ll have from not having to manually track down all those closed web parts.
-Frog Out
Links
Display closed web parts PowerShell Script
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#547033Brian, this is an awesome script. I actually asked Brian G if this was possible and it looks like he went to the right place. I’m getting several errors during the crawl, but I’m guessing it’s due to bad links or errors on the pages. I’ll work that out some day. We’ll use this this script for a lot of other site discoveries we want to do. Thank you very much!It’s important to point out for other people that the input requires an actual site and not a root-level web app. So you need http://xxxx/sites/yyy and not just http://xxxx. Also, I modified the script slightly for me to add some logging to a text file. It’s quick and dirty, but it works. I replaced the section following the function with this:Set-ExecutionPolicy RemoteSigned[void][System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)$dt = Get-Date -format “yyyyMMdd_hhmm”$LogFile = “ClosedWebPartAudit-$dt.txt”Start-Transcript $LogFile # Start a transcript to log all activities for auditing$siteUrlToSearch = Read-Host -Prompt “Enter site URL to check for closed web parts”Search-SPClosedWebParts -SiteUrl $siteUrlToSearchStop-Transcript # Stop the transcript
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#547223Brian L., You are correct that this script may have a few bugs when it comes to searching through the hierarchy. I found an issue when testing a page that was in the site definition but had been deleted. Also note that this script does not recursively run through all site collections and subsites within a web application, only the site collection and direct subsites for the URL provided. I only intended this script as a beginning point for others to get started and build on as they see fit. If time permits I’ll look into upgrading this to handle other scenarios, but for now my time is pretty limited. Glad you were able to find it useful. Thanks for reading.
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#591605Brian, i am interested to analyzing my farm to find sites that do (and do not) contain the Contact Details web part. Any suggestions on how i could modify your script to accomplish my goal would be greatly appreciated.Thanks
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#591823Dean,There are multiple ways to recursively traverse every site in a farm, but each takes a little bit of coding to be done. Your comment spurred me to finally write up a concise script that will do that. I’ll try to get it posted later this week. In the meantime the basic premise is to pull all web applications from the farm, all site collections from the web applications, then recursively traverse all webs within the root web on a site collection.
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#593590I have tried but get an error on”GetLimitedWebPartManager” with “2” argument(s): “fullOrRelativeUrl”When I fill an URL either with the SiteCollection URL or an actual default.aspx page – both paths send the script to go through all webs in my site collection. Any pointers/ideas how to solve this?
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#595396Nico,Are you saying you get an error when running the script or that it is not performing as intended?The script is written to traverse all sites within the site collection of the URL you provide. Do you get a valid reference to the site collection after this line:$site = new-Object Microsoft.SharePoint.SPSite($SiteUrl)
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#603209Brian,Yet again Google has led me to your blog. I was looking for a script to list all of the webparts on pages, so I modified your script to also write out the open ones as well. I also had the same error for some of the web parts as Nico.Thanks for posting your script.
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#621713Brian,Thanks for the script. However this script scans only the Root of the SharePoint site. I’ve written a PowerShell script to Find and Delete closed Web parts on All pages.Closed Web Parts in SharePoint – How to Find, Restore and DeleteRegards,Sal
LikeLike
Originally posted on: https://briantjackett.com/archive/2010/11/11/powershell-script-to-find-all-closed-web-parts-on-sharepoint.aspx#621740Sal,You are correct, my script did not search subfolders for pages. I can’t remember in 2007 if the Files property captured all files or only ones at the root. Thanks for your link though, good comparison case.
LikeLike