Share via


SharePoint 2007: How to Remove Orphaned Features Using PowerShell

I recently had to use content deployment on some old MOSS 2007 systems. These systems are alive for a long time and a lot of solutions/features have been deployed to them. 

If features are not deactived before removal they stay as an orphan in the system (contentdb) and can cause issues lateron. I had to cleanup orphaned features before the content deployment worked properly. 

The procedure for identyfing and removing orphaned features is quite straightforward:

  1. Go through every site collection and site recursively
  2. For each SPWebApp, SPSite and SPWeb
  3. Iterate through the *.Features collection
  4. For each feature, if the definition is null the script removes it from the feature collection 
[system.reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint")            
function ListFeaturesAux($header, $features, $obj, $boolremove)                        
{                        
    foreach ($feature in $features)                        
    {                        
        if( $feature.Definition -eq $NULL)                        
        {                        
   write-host "Missing feature definition (feature id:" $feature.DefinitionId  "), Scope: "  $header                        
            if( $boolremove -eq $TRUE)                        
            {                        
                try                         
    {                        
     $obj.Features.Remove($feature.DefinitionId,$true)                        
     write-host "Feature "  $feature.DefinitionId " has been removed."                         
                }                        
    catch                         
    {                        
     write-host "An error occured while removing feature:"  $feature.DefinitionId                        
    }                        
            }                     
  }                         
    }                        
}                        
                         
function ListFeaturesWeb($web, $boolremove)                        
{                             
    $header = "Web: " +  $web.Url                        
    ListFeaturesAux $header $web.Features $web $boolremove                        
    foreach( $subweb in $web.Webs)                        
    {                        
        ListFeaturesWeb $subweb $boolremove                        
    }                        
}                        
                         
function ListFeaturesSite($site, $boolremove)                        
{                        
    $header = "Site collection: " +  $site.Url                        
    ListFeaturesAux $header  $site.Features $site $boolremove                        
}                        
                         
function list-orphaned-Features ($url,$boolremove)                        
{                         
    $webapp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($url)                        
    write-host $webapp.displayname                            
    foreach($Site  in $webapp.Sites )                        
 {                        
  ListFeaturesSite $Site $boolremove                        
  ListFeaturesWeb $Site.RootWeb  $boolremove                        
 }                        
}                        
                         
#change parameter boolremove from $false to $true to remove the feature                        
list-orphaned-Features "http://sp2007"  $false