// you’re reading...

Uncategorized

SharePoint PowerShell: Remove duplicate WebParts

Last week I received an email from a colleague who was having problems with a SharePoint 2007 upgrade.  Actually, the upgrade went fine, but when he moved a Publishing Site Collection to a subsite of an existing site collection, he ran into several problems, one of which was that each page had a duplicate set of web parts.  

I was about to go on vacation, but I had just published my PowerShell extensions and thought it would be a good opportunity to use them.  So, in one of my prouder moments, I free-handed about 10 lines of PowerShell into an email and left town.  I was delighted to find out that the code actually worked (once you removed the incorrect characters that Outlook had injected).

So, here’s a quick little blog post explaining what I did.

First, I spooled up a standalone SharePoint 2010 VM and ran PowerShell ISE.

Then I did the following to initialize my extensions:

cd \VboxSvr\host_m\Development\wfPowerShell
. .\Boostrapper.ps1

Next I needed a page to play with, so I created a test web part page and added a couple of web parts:

Now, I could have manually created the dupes, but it was more fun to try it with a script:

</p><h1>This function has virtually no practical application :)</h1><p>filter Duplicate-WebParts(){ $Page = $_
$webparts = $Page | Export-WebParts
$Page | Import-WebParts -WebPartInfos $webparts
}

$page = Get-SPWebRelative / | Get-SPFile 'Shared Documents/TestDupes.aspx'
1..3 | % { $page | Duplicate-WebParts | out-null }

 

This produced the following output:

11:36:24 PM Imported web part: Web Part Page Title Bar    [Microsoft.SharePoint.WebPartPages.TitleBarWebPart]
11:36:27 PM Imported web part:     [Microsoft.SharePoint.WebPartPages.XsltListViewWebPart]
11:36:28 PM Imported web part: Content Editor    [Microsoft.SharePoint.WebPartPages.ContentEditorWebPart]
11:36:33 PM Imported web part: Web Part Page Title Bar    [Microsoft.SharePoint.WebPartPages.TitleBarWebPart]
11:36:33 PM Imported web part:     [Microsoft.SharePoint.WebPartPages.XsltListViewWebPart]
11:36:34 PM Imported web part: Content Editor    [Microsoft.SharePoint.WebPartPages.ContentEditorWebPart]
11:36:35 PM Imported web part: Web Part Page Title Bar    [Microsoft.SharePoint.WebPartPages.TitleBarWebPart]
11:36:36 PM Imported web part:     [Microsoft.SharePoint.WebPartPages.XsltListViewWebPart]
11:36:37 PM Imported web part: Content Editor    [Microsoft.SharePoint.WebPartPages.ContentEditorWebPart]

Since I ran it through my duplication function 2x, I now have 4 versions of each of the original webparts, as shown in the image below:
Finally, I tweaked my free-handed script with some better arguments and logging:

filter Remove-DuplicateWebParts([switch] $WhatIf, $DupeProperties = @('Title', { $_.GetType() })) {
    $Page = $_
    Log "processing WebPart duplicates in $($page.ServerRelativeUrl)"
    $webparts = $page | Get-WebParts
    $dupeGroups = $webparts | group $DupeProperties | where { $_.Count –gt 1 }
    $allDeletions = $dupeGroups | lwp -ActionLabel "Processing Dupe Group" -StatusReportBlock { $_.Name }  | % {
        $keep, $deletions = $_.Group
        return $deletions
    }
    if(!$WhatIf){
        $page | modify-webparts –delete –filter {
            ($allDeletions |> Id ) -contains $_.Id
        } | lwp -Action Deleted -Status { "$($_.Title) ($($_.Id))" } | log-item -prefix 'deleted '  -Process {"$($_.Title) ($($_.Id))"}  | out-null
    } else {
        $allDeletions | log-item -prefix "Delete " -Process {"$($_.Title) ($($_.Id))"} | out-null
    }
    return $Page
}

$page = Get-SPWebRelative / | Get-SPFile 'Shared Documents/TestDupes.aspx'
#1..2 | % { $page | Duplicate-WebParts | out-null }
$page | Remove-DuplicateWebParts | out-null

A couple of notes about what is going on here:
  • Using a filter is a quick/dirty way to support pipeline input, which is often terser and more fluid than using arguments
  • The simplest way to identify collections of dupes is to use the group function and supply a list of properties that, altogether, should make a webpart unique.
  • After identifying the dupes, loop through them, skipping the first one (which is the one we will $keep)
  • modify-webparts is my catch-all cmdlet for modifying, deleting, and closing webparts.  I could have also just obtained a webpart manager and manually deleted, but this cmdlet makes it a no-brainer (and I was also looking for an excuse to demo it)
When executed, the script above produced the following output:

11:36:39 PM processing WebPart duplicates in /Shared Documents/TestDupes.aspx
11:36:42 PM deleted Web Part Page Title Bar (g<em>7571f1e5</em>1238<em>48d7</em>a029<em>66acf59d7a9c)
11:36:42 PM deleted Shared Documents (g</em>edb5d78a<em>c5ad</em>4f75<em>b134</em>01716c46f7eb)
11:36:43 PM deleted Content Editor (g<em>6f02ef6a</em>6c52<em>4c1c</em>864b<em>553dcddb27f8)
11:36:43 PM deleted Web Part Page Title Bar (g</em>19c9e065<em>4ac6</em>4329<em>9d3c</em>445b63cfac4e)
11:36:43 PM deleted Shared Documents (g<em>d1c7659a</em>6b26<em>43c2</em>88d7<em>b767349f689b)
11:36:43 PM deleted Content Editor (g</em>dc6cbcaf<em>0705</em>462e<em>ba39</em>a9fae18682fe)
11:36:43 PM deleted Web Part Page Title Bar (g<em>e1a26dc2</em>cc6f<em>49b6</em>bccd<em>ef825ab56dea)
11:36:43 PM deleted Shared Documents (g</em>20d52916<em>1bad</em>4c4c<em>9374</em>2fb27296b6cb)
11:36:43 PM deleted Content Editor (g<em>e1847600</em>d1f1<em>43c7</em>a83d_08f2273ac7ba)

and my page now looks like this (again):

Discussion

No comments for “SharePoint PowerShell: Remove duplicate WebParts”

Post a comment