Powershell to find missing features in SharePoint 2010

Posted by Rik Hepworth on Friday, November 19, 2010

When migrating from SharePoint 2007 to 2010, no matter how hard you try there’s always the chance the the content database upgrade process will throw out errors about features being referenced that are not present in the farm. We have used Stefan Goßner’s WssAnalyzeFeatures and WSSRemoveFeatureFromSite (see his original article) to track down the references and exterminate them. It’s not the fastest thing on two legs though, and I have a fondness for having my SharePoint 2010 tooling in PowerShell because of the flexibility it gives me.

Here then, with a big hat-tip to Stefan, is the PowerShell to replicate his functionality. We differ slightly, in that I wanted one command to purge both site- and web-referenced features in one shot rather than calling a command with a scope switch. I have two functions – get-spmissingfeatures takes a Site Collection url as a parameter and scans through site and web feature collections, listing any features with a null definition property. The second function, remove-spmissingfeatures takes the same url and this time finds and removes the errant features in one pass.

Get-SpMissingFeatures:

function get-spmissingfeatures([string]$siteurl)  
{  
  $site = get-spsite $siteurl`

  
  foreach ($feature in $site.features) {  
    if ($feature.definition -eq $null) {  
      write-host "Missing site feature:"  
      write-host $feature.DefinitionId  
      write-host $feature.parent  
    }  
  }

  $webs = $site | get-spweb -limit all  
  foreach ($web in $webs) {  
  foreach ($feature in $web.features) {  
    if ($feature.definition -eq $null) {  
      write-host "Missing web feature:"  
      write-host $web.url  
      write-host $feature.DefinitionId  
      write-host $feature.parent  
      }  
    }
  }
}

Remove-SPMissingFeatures:

function remove-spmissingfeatures([string]$siteurl)  
{  
  $site = get-spsite $siteurl`

  
  foreach ($feature in $site.features) {  
    if ($feature.definition -eq $null) {  
      write-host "Missing site feature:"  
      write-host $feature.DefinitionId  
      write-host $feature.parent  
      $site.features.remove($feature.DefinitionId)  
    }  
  }

  $webs = $site | get-spweb -limit all  
  foreach ($web in $webs) {  
    foreach ($feature in $web.features) {  
      if ($feature.definition -eq $null) {  
        write-host "Missing web feature:"  
        write-host $web.url  
        write-host $feature.DefinitionId  
        write-host $feature.parent  
        $web.features.remove($feature.DefinitionId)  
      }  
    }
  }  
}