I’ve been working on knocking out some issues from the Pre-Upgrade Check Report in order to get ready for our upgrade to SharePoint 2010 and recently hit one heck of a snag where certain artifacts that were created way back in 2003 were somehow still being referenced but not actually used anywhere in 2007. These items never existed in the 2007 file system and were certainly not visible in any way from the UI.
The items appeared under the “Missing server file or server configuration issues” section of the report under the specific title of “The following setup file(s) are referenced by the content, but they are not installed on the web server”. They were part of old Site Templates that were fortunately all named starting with “STSFA”. To find out where SharePoint thought these items were required diving into the content database (Sorry, but the additional data Microsoft provides for these errors is close to useless) the SQL used is below but the fields of concern are DirName and LeafName:
select * from AllDocs with (nolock) where SetupPath like 'SiteTemplates\STSFA%' order by DirName
In my case, I had the following URLs that were being kicked out – “/RealFolder/03folder/default.aspx”. RealFolder exists (obviously) but 03Folder does not, yet SharePoint claimed it did on the Pre-Upgrade report.
It turns out that these items were in a state where, depending on how you looked at them, they were either orphaned or were not orphaned. Go ahead, put on your Kenobi robe on and wrap your brain around that, I’ll wait. Back? Ok, good. Perhaps a better term for these types of items might be “disowned” rather than orphaned.
After some digging in the Object Model, it turned out that if you use certain methods to access the item, like GetFile() or GetFolder() that it could see the items but it only returns a subset of the data that SharePoint has about the object. The objects returned from these methods always had several properties, including ParentWeb listed as empty. When I attempted to call .Delete() on the item, it would throw the ever popular “Object or reference not set…” exception.
The PowerShell below is a summary of how I got past that issue and it includes the comments as to why the steps are there. Yes, I could have written this as a C# console application as well, but I wanted to keep it in PowerShell so that the other Admins would know exactly what the script was doing.
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") [Microsoft.SharePoint.SPSite]$site = [Microsoft.SharePoint.SPSite]("http://SiteUrlGoesHere/") $fileUrl = "http://SiteUrlGoesHere/RealFolder/03Folder/default.aspx" #get a handle to the web that thinks it contains the orphan [Microsoft.SharePoint.SPWeb]$parentWeb = $site.OpenWeb($fileUrl, $false) #Get a handle to the object itself. #for some reason, this call brings back way more information than GetFile(),
#not the least of which is the Guid to the actual object $tempFile = $parentWeb.GetObject($fileUrl) #use the Guid to get the real object [Microsoft.SharePoint.SPFile]$oldFile = $parentWeb.GetFile($tempFile.UniqueId) #Now make all your dreams come true #oldFile.Delete() #but don't forget to clean house $parentWeb.Dispose()
I tried about 7 variations on the above method, including trying to open the items from the root of the site, using GetFile() directly, etc.. This was the only version I tested that actually deleted the items from the SharePoint database.
The best part about this is that the update is done completely via the Object Model so it is a fully supported way to cleanup these types of orphaned files.