Saturday, May 14, 2011

PowerShell to remove web parts with errors from SharePoint 2010

One of the things that I run into whenever I do an upgrade from an older version of SharePoint to SharePoint 2010 is that not all of the custom functionality previously implemented still works. This is especially true when moving from WSS 2.0 to SharePoint 2010.

When a client has 50+ sites and these web parts are on every landing page the process of removing them manually is just out of the questions. So how do we solve this?

Well, in SharePoint 2007 I would have said that you should go bug a developer and have them write you a console application to loop through and remove any and all erroring web parts. However, in SharePoint 2010 the story is slightly different.

PowerShell to the rescue!!!

function Remove-SPErroringWebParts
{
[CmdletBinding()]

param
(
[parameter(ValueFromPipeline=$true,Mandatory=$true,Position=0)]
$Web
)

begin
{
Out-Host -InputObject "Beginning Remove-SPErroringWebParts..."
}

process
{
if ($Web -is [string]) {Out-Host -InputObject " This is a string.";$Web = Get-SPWeb $Web}
if ($Web -is [Microsoft.SharePoint.Administration.SPWebApplication]) {Out-Host -InputObject " This is a web app.";$Web = Get-SPSite -WebApplication $Web -Limit All -Confirm:$false}
if ($Web -is [Microsoft.SharePoint.SPSite[]]) {Out-Host -InputObject " This is an array of sites.";$Web | %{Set-AllBackToSiteDefinition -Web $_}}
if ($Web -is [Microsoft.SharePoint.SPSite] ) {Out-Host -InputObject " This is a site.";$Web = (Get-SPWeb -Site $Web -Limit All -Confirm:$false)}
if ($Web -is [array]) {" This is an array."; $Web | %{ Remove-SPErroringWebParts $_ } }
if ($Web -is [microsoft.SharePoint.SPWeb])
{
Out-Host -InputObject " This is a web."
$webpartmanager = $Web.GetLimitedWebPartManager(($Web.Url + "/default.aspx"), [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)

#Create a separate list of webparts to be deleted to avoid enumeration error
$webpartsToDelete = $webpartmanager.WebParts | ?{$_.ErrorMessage -ne $null}

foreach ($webpart in $webpartsToDelete)
{
if ($webpart.ErrorMessage -ne $null)
{
Out-Host -InputObject " Deleting webpart.."
$webpartmanager.DeleteWebPart($webpart)
}
}
$Web.Dispose()
}
}

end
{
Out-Host -InputObject "Finished Remove-SPErroringWebParts."
}
}



The function above looks far more complicated than it really is. I wrote it so that I could save it off and use it for later projects. To be honest, this function isn’t really done as I need to add a great deal of error handling, it only checks the “/default.aspx” page so if you have Publishing sites or even sites that use the Wiki Home Page it will not work, and there is some Out-Host commands that will most likely be changed to Out-Debug. However, I digress. Writing PowerShell for reusability is a completely different discussion that I will probably write about at a later date. Until then there are a couple really great blog posts you can check out if you are interested:




For now, lets take a look at what a more minimalistic approach would be.




$Web = Get-SPWeb "http://site/web"
$webpartmanager = $Web.GetLimitedWebPartManager(($Web.Url + "/default.aspx"), [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$webpartsToDelete = $webpartmanager.WebParts | ?{$_.ErrorMessage -ne $null}
foreach ($webpart in $webpartsToDelete)
{
if ($webpart.ErrorMessage -ne $null)
{
Out-Host -InputObject " Deleting webpart.."
$webpartmanager.DeleteWebPart($webpart)
}
}
$Web.Dispose()



Much less code there but less power as well. This will obviously only work on an SPWeb object and the code would need to be adjusted for any other scope. Let’s take a look at the usage of the original function.

On an SPWeb object:




Get-SPWeb "http://server/site/web" | Remove-SPErroringWebParts


On an SPSite object:


Get-SPSite "http://server/site" | Remove-SPErroringWebParts


On an SPWebApplication object:


Get-SPWebApplication "http://server" | Remove-SPErroringWebParts


Or on an string:


"http://server/site/web" | Remove-SPErroringWebParts





Either way the function will loop through all of the “/default.aspx” pages on the SPWeb objects of the given scope and remove any web parts that have errors.

I’m sure I don’t have to tell you that this can be just as dangerous as it is helpful if you have web parts that are erroring that you are not aware of. As always use caution and I’m not responsible for anything you break while using anything you find here. Smile


I hope this helps! Any and all feedback is welcomed and appreciated. Let me know what you think!

No comments: