A client migrated from 2007 to 2010 doing a database detach/reattach without checking the database for orphaned objects first. I whipped up a PowerShell script to programmatically remove orphaned WebParts that generate "Missing server side dependencies" errors in CA Health Analysis like:
[MissingWebPart] WebPart class [GUID] is referenced [1] times in the database [ContentDBName], but is not installed on the current farm. Please install any feature/solution which contains this web part. One or more web parts are referenced in the database [ContentDBName], but are not installed on the current farm. Please install any feature or solution which contains these web parts.
When I try to remove a WebPart programmatically it tells me:
Exception calling "DeleteWebPart" with "1" argument(s): "The file is not checked out. You must first check out this document before making changes."
At C:\RemoveWebParts.ps1:47 char:31
+ $spWpManager.DeleteWebPart <<<< ($spWpManager.Webparts[$webpartId])
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
So I implemented code to check out the page and check it back in after it's removed (if I checked it out) and now it's telling me:
Exception calling "DeleteWebPart" with "1" argument(s): "The file is currently checked out or locked for editing by another user."
At C:\RemoveWebParts.ps1:53 char:31
+ $spWpManager.DeleteWebPart <<<< ($spWpManager.Webparts[$webpartId])
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Which obviously is an issue. When it's not checked out it says it has to be checked out, and when it is checked out it says it's checked out by another user (even though the SharePoint 2010 Management Shell is running as my user, and I can verify my user is the user the page is checked out to).
Why could this be? How can I resolve it?
Edit
Here is the code (site hierarchy traversal omitted for brevity):
$spWpManager = $spweb.GetLimitedWebPartManager($WebPageUrl, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared);
$webparts = @()
if ($item.File.CheckOutType -ne "None")
{
$checkedOut = $checkedOut + $WebPageUrl + ","
}
foreach($spwebpart in $spWpManager.Webparts)
{
if($spwebpart.Title -eq $wpName)
{
$webparts = $webparts + $spwebpart.ID
}
}
foreach($webpartId in $webparts)
{
if (!$bool)
{
$item.File.CheckOut()
$bool=$true
}
$spWpManager.DeleteWebPart($spWpManager.Webparts[$webpartId])
}
if ($bool)
{
$item.File.CheckIn()
$bool=$false
}
$spWpManager.DeleteWebPart(). – RJ Cuthbertson Aug 07 '12 at 13:05Edit the script based on your requirements.
– user994521 Aug 15 '12 at 01:02