SharePoint Features Usage Report using PowerShell

Task: Generate a report for All Installed/Activated Features for the entire SharePoint Environment. Here are some nifty PowerShell scripts to find features installed on the farm as well as specific features activated on a particular scope.

Get-SPFeature cmdlet:
Get-SPFeature cmdlet retrieves all features installed on the environment when the “Scope” parameter’s value is not supplied. It gets all activated features on the particular scope, when you provide scope parameter: (Such as: -site “https://sharepointsite.com”)

Get a list of all installed SharePoint features, grouped by feature scope:

Get-SPFeature | Sort-Object Scope | Format-Table -GroupBy scope
SharePoint Features Usage Report using PowerShell

Lets export to a text file:

Get-SPFeature | Sort -Property Scope, DisplayName | Ft -Autosize -GroupBy Scope DisplayName, Id > D:\FeaturesReport.txt

To get all features activated at a particular web application scope, Use:

Get-SPFeature -WebApplication "web-app-url"
#Similarly:
#Get-SPFeature -Farm
#Get-SPFeature -Site $Site.URL
#Get-SPFeature -Web $web.URL

Get All Features along with their title:

Get-SPFeature | Format-Table @{Label='ID';Expression={$_.Id}}, 
@{Label='DisplayName';Expression={$_.DisplayName}}, 
@{Label='Title';Expression={$_.GetTitle(1033)}}, 
@{Label='Scope';Expression={$_.Scope}} -AutoSize | Out-File -Width 250 
D:\AllFeatures.txt

Get All Feature Tiles and Description, Activated on a Particular Site collection:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$siteurl = "https://sharepoint.crescent.com"

Get-SPFeature -Limit ALL -Site $siteurl | ForEach-Object {
  $data = @{ 
  Feature = $_.GetTitle(1033)
  Description = $_.GetDescription(1033)
 }
 New-Object PSObject -Property $data; 
} | Select-Object Feature, Description 

Find all/specific Feature in SharePoint 2013 / SharePoint 2010:
Lets find and list where a feature is activated.

Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue

$FeatureName = "TemplateDiscovery"
#We can also use "FeatureID" instead of Feature DisplayName 

# Get all Farm scoped features
#write-host "Farm scoped features:"
#Get-SPFeature -Farm 

# To Search for a specific Farm scoped feature:
Get-SPFeature -Farm | where { $_.DisplayName -eq $FeatureName } #Eg SpellChecking

 #Process All Web Applications
 ForEach ($WebApp in Get-SPWebApplication)
 {
    write-host "`nProcessing Web Application:" $webapp.url  
    #Get All Web Application Scoped features 
    #Get-SPFeature -WebApplication $WebApp.url 

    # To Search for a specific WebApplication scoped feature:
    Get-SPFeature -WebApplication $WebApp.url | where { $_.DisplayName -eq $FeatureName }

    #Process each site collection
    foreach ($site in $WebApp.sites) 
    {
      write-host "`tProcessing Site Collection: " $site.url 
      #Get All Site collection Scoped features 
      #Get-SPFeature -Site $site.url 

      # To Search for a specific Site Collection scoped feature:
      Get-SPFeature -Site $site.url | where { $_.DisplayName -eq $FeatureName }

      #Process each site
      foreach ($web in $site.AllWebs) 
      {
         write-host "`t`tProcessing Web: " $web.url 
         # Get All Web scoped features
         #Get-SPFeature -Web $web 

         # To Search for a specific Site Collection scoped feature:
         Get-SPFeature -Web $web | where { $_.DisplayName -eq $FeatureName }
       }
    }
 }

Feature inventory for SharePoint 2007 using STSADM:
Stsadm -o enumallwebs -includefeature

Using PowerShell to find all features in MOSS 2007:
This script gets all activated features scoped at web application, Site Collection, Site scopes:

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

Function global:Get-SPWebApplication($WebAppURL)
{
 return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
}

  #Get the SharePoint Farm. Equallent to : Get-SPFarm commandlet
  $Farm = [Microsoft.SharePoint.Administration.SPFarm]::Local

  #Get All feature of the farm. Equallent to: Get-SPFeature commandlet
  $FarmFeatures= $Farm.FeatureDefinitions
  
  $WebAppURL = "https://SharePoint.Crescent.com"
  $WebApp = Get-SPWebApplication $WebAppURL
  
   #Scan Web Application Features
    Write-Host  "Features Activated at Web Application Level:"  -ForegroundColor DarkGreen

   foreach($feature in $WebApp.Features)
   {
      #Write-Host $feature.DefinitionId;
      Write-Host $farmfeatures[$feature.DefinitionId].DisplayName 
   }
  
  #Get All site collections of the Web Application  
  $SitesColl = $webApp.Sites  
  
  #Iterate through each site collection/sub-site
  foreach($Site in $SitesColl)
  {
   Write-Host "`nFeatures Activated at SITE:" $site.Url -ForegroundColor DarkGreen

   #Iterate through each feature activated at Site collection level
   foreach($feature in $site.Features)
   {
      #Write-Host $feature.DefinitionId;
      Write-Output $farmfeatures[$feature.DefinitionId].DisplayName;
   }
    foreach($web in $site.AllWebs)
    {
       Write-Host "`nFeatures Activated at WEB:" $web.Url -ForegroundColor DarkGreen
       #Iterate through each feature activated at web level
       foreach($Feature in $web.Features)
       {
          Write-Output $FarmFeatures[$Feature.DefinitionId].DisplayName;
          #Write-Output $FarmFeatures[$Feature.DefinitionId].GetTitle(1033);
       }
    }
  }

Get-SPFeature Cmdlet for SharePoint 2007:
Powershell script to report all SharePoint Farm Feature

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

#Get the SharePoint Farm. Equallent to : Get-SPFarm commandlet
$Farm = [Microsoft.SharePoint.Administration.SPFarm]::Local

#Get All feature of the farm. Equallent to: Get-SPFeature commandlet
$FarmFeatures= $Farm.FeatureDefinitions
$FarmFeatures | Select ID,DisplayName, Scope | Sort-Object Scope | Format-Table -GroupBy Scope
Tip: To find out all SharePoint enterprise feature usage, use: PremiumWebApplication, PremiumSite, PremiumWeb accordingly on Feature Display Names.

Find a Particular Feature’s usage in SharePoint 2007:

#Get-SPWebApplication Cmdlet for MOSS 2007
Function global:Get-SPWebApplication($WebAppURL)
{  
   if($WebAppURL -eq $null)  #Get All Web Applications
    {
  $Farm = [Microsoft.SharePoint.Administration.SPFarm]::Local
    $websvcs = $farm.Services | where -FilterScript {$_.GetType() -eq [Microsoft.SharePoint.Administration.SPWebService]}
    $WebApps = @()
    foreach ($websvc in $websvcs) 
  {
      foreach ($WebApp in $websvc.WebApplications) 
   {
          $WebApps += $WebApp
      }
  }
   return $WebApps
  }
 else #Get Web Application for given URL
 {
  return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
 }
}

  #Get the SharePoint Farm. Equallent to : Get-SPFarm commandlet
  $Farm = [Microsoft.SharePoint.Administration.SPFarm]::Local

  #Get All feature of the farm. Equallent to: Get-SPFeature commandlet
  $FarmFeatures= $Farm.FeatureDefinitions
  
  #Feature to Search
  $FeatureDisplayName = "IPFSWebFeatures" #Infopath Form Services Feature
  
  #Scan Farm Level Features
  $FarmLevelFeatures = $farm.FeatureDefinitions | Where-Object { ($_.Scope -eq "Farm") -and ($_.DisplayName -eq $FeatureDisplayName) }
  if($FarmLevelFeatures -ne $null)
  {
   "$($FeatureDisplayName) Installed at Farm Level!"
  }
   
   #Get all web applications and scan through 
   $WebApplications = Get-SPWebApplication "https://sharepoint.crescent.com"
   #To process all web applications, simply use: $WebApplications = Get-SPWebApplication 
   foreach($WebApp in $WebApplications)
   {
  Write-Host "Processing web Application : $($WebApp.url)"
  $WebAppLevelFeature = $webApp.Features |  Where-Object { $_.Definition.DisplayName -eq $FeatureDisplayName }
  #If Feature found
  if($WebAppLevelFeature -ne $null)
  {
  "$($FeatureDisplayName) Activated at Web Application $($webApp.URL)"
  }
    
  #Get All site collections of the Web Application  
  $SitesColl = $webApp.Sites  
  
  #Iterate through each site collection
  foreach($Site in $SitesColl)
  {
      #Write-host "Processing Site: $($Site.Url)"
   $SiteLevelFeature = $Site.Features |  Where-Object { $_.Definition.DisplayName -eq $FeatureDisplayName     }
   #If Feature found
   if($SiteLevelFeature -ne $null)
     {
    "$($FeatureDisplayName) Activated at Site Collection $($Site.URL)"
     }
    
    #Enumerate each sub-site
    foreach($web in $site.AllWebs)
    {
         #Write-host "Processing Web: $($Web.Url)"
         $WebLevelFeature = $web.Features | Where-Object { $_.Definition.DisplayName -eq $FeatureDisplayName }
    #If Feature found
     if($WebLevelFeature -ne $null)
        {
          "$($FeatureDisplayName) Activated at Web Level $($web.URL)"
        }
     $web.Dispose()
  }
   $site.Dispose()
  }
}

How do I find all custom features?
We can run Get-SPFeature on a fresh sharepoint machine, take that inventory in a csv file.
Run it again in your targt machine which has custom features and compare!

Lately, Found this script on Technet Forums:

Add-PSSnapin "Microsoft.SharePoint.Powershell" -ErrorAction SilentlyContinue

$siteurl = "https://sharepoint.crescent.com"
$Site = Get-SPSite $siteURL

#send all features to output file features.txt
$site.WebApplication.Farm.FeatureDefinitions `
| where-object {$_.solutionid -ne '00000000-0000-0000-0000-000000000000'} `
| Sort-Object solutionid,displayname `
| ft -property displayname,scope -auto -groupBy solutionid > "d:\features.txt"

#replace solutionId in features.txt with solution name
foreach($solution in $site.WebApplication.Farm.Solutions)
{
    (Get-Content "d:\features.txt") `
    | Foreach-Object {$_ -replace $solution.solutionid.ToString(), $solution.Name} `
    | Set-Content "D:\features.txt"
}

$site.Dispose()

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. Passionate about sharing the deep technical knowledge and experience to help others, through the real-world articles!

Leave a Reply

Your email address will not be published. Required fields are marked *