Cleaning up obsolete SharePoint groups

During the lifetime of a SharePoint implementation, sites come and go. When a site collection grows, you typically see the amount of SharePoint groups growing as well because you want to give people access to those sites in a sort of organized way. When sites go, those groups are left behind. Removing those obsolete SharePoint groups can be a challenging task because groups which have been created for a specific site can be used for other sites as well. So, before removing a group, you need to be sure that it’s not used on any other sub sites.

SharePoint groups live on the root web of a site collection.

If a group is created as part of the site creation process, it will have a description which clearly states for which site is has been created. This doesn’t mean it can’t be used on any other sites. If you want to get a list of all SharePoint groups which exist in a site collection, you can also use the following PowerShell snippet to get the collection.

$site = Get-SPSite <SiteColURL>
$site.RootWeb.SiteGroups | Select Name, Description

If you want to know which groups are used on a specific subsite of the site collection, you can use the UI and check the Site Permissions section of a site. This will give you all permissions for that site. You can also use the following PowerShell snippet to get these.

$web = $site.RootWeb
$web.Groups | Select Name, Roles

See the difference? The SiteGroups has a group “MyCustomGroup” which is not part of the Groups collection of the same web. This means that the group exists in the site collection but at this point, it’s not used. When I give this group explicit permissions to my site, it will be added to this collection and it will be in use.

So, the process of cleaning up obsolete groups is to check the Groups collection on each sub site and see which site groups are used for giving people access. If you have a site group which is not part of any Groups collection of any site, it’s not used and you can remove that group from the site collection.

You can do this manually, or you can automate this process and use the following script for this task.

This script will do 2 things.
If run in Simulation mode, it will look for obsolete groups and ouput them to the console. Nothing more.
If run in Execution mode, it will look for obsolete groups and delete them from the site collection.

    Identify unused SharePoint groups and delete them.
    Identify unused SharePoint groups and delete them
    File Name: Delete-UnusedGroups.ps1
    Author   : Bart Kuppens
    Version  : 1.0
    Specifies the URL of the site collection to cleanup.

    If included, obsolete groups are outputted to the screen and NOT deleted (SIMULATION mode).
    If omitted, obselete groups are deleted (EXECUTION mode). 

    PS > .\Get-UnusedGroups.ps1 -Site http://teamsites.westeros.local -ViewOnly
    [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Specifies the URL of the site collection to cleanup.")] 
    [Parameter(Position=1,Mandatory=$false,ValueFromPipeline=$false,HelpMessage="If true, obsolete groups are outputted to the screen and NOT deleted.")] 
if ( (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
    Write-Host "Loading SharePoint cmdlets..."
    Add-PsSnapin Microsoft.SharePoint.PowerShell

$SPSite = Get-SPSite $site
if ($SPSite -eq $null)
    Write-Host "There's no site at URL $site. Halting execution!"

if ($ViewOnly)
    Write-Host -ForegroundColor Red -BackgroundColor Yellow "Running in SIMULATION mode!!!"
    Write-Host -ForegroundColor Red -BackgroundColor Yellow "Running in DELETE mode!!!"

$groups = $SPSite.RootWeb.SiteGroups
$groupsToDelete = @()

$nbrGroups = $groups.Count
$percGroups = 100 / $nbrGroups
$compGroups = 0
$nbrObsoleteGroups = 0

foreach ($group in $groups)
    $hasAccess = $false
    $compGroups += $percGroups
    Write-Progress -Activity "Checking obsolete groups ($nbrObsoleteGroups/$nbrGroups found)" -Status $group.Name -PercentComplete $compGroups
    # Check if this group has been given access to a subsite
    $webs = $SPSite.AllWebs
    if ($webs.Count -gt 0)
        foreach ($web in $webs)
            if ($web.Groups["$group"] -ne $null)
                $hasAccess = $true
    if ($hasAccess -eq $false)
        $groupsToDelete += $group

if ($ViewOnly)
    Write-Host "$($groupsToDelete.Count) groups were found."
    if ($nbrObsoleteGroups -gt 0)
        Write-Host "Following groups would be removed in DELETE mode"
        $groupsToDelete | Select Name
    $nbrGroups = $groupsToDelete.Count
    $percGroups = 100 / $nbrGroups
    $compGroups = 0
    $i = 1
    foreach ($item in $groupsToDelete)
        $compGroups += $percGroups
        Write-Progress -Activity "Deleting group $i/$nbrGroups" -Status $item.Name -PercentComplete $compGroups

My advice… run it in Simulation mode before running it in Execution mode. That way, you have an idea of what groups were found and will be deleted.

There are some situations which need clarifications.

Inherited permissions

What happens when you have subsites which inherit permissions? This is no issue. Suppose you have a subsite which inherits permissions of the root web of the site collection. When a SharePoint group is given access to the root web of the site collection, it will be given access to all sub sites which inherit their permissions and as such, that group will be part of the Groups collection of those sub sites.

Audience targeting

What happens when a group is exclusively used for audience targeting? Well, this is a problem because that group is not part of the Groups collection of the site where you have used it as an audience. In my opinion, this is a situation you should avoid doing because you are going to give a collection of users access to a site. In theory, an audience is a subset of authorized users, right? You want to target specific content on a site to specific users. If they can’t reach the site, what’s the point in targeting content to them?

If you do find yourself in such a situation where you have SharePoint groups which are exclusively used for audience targeting, a good approach would be to give those groups distinctive names, clearly indicating they are audience targeting groups. For example, you could start each group name with “AUD_”. This way, you can extend the script above and include a check to skip groups which start with “_AUD”.

By Bart

Bart is a certified SharePoint consultant / architect at CTG Belgium NV with a broad professional experience in IT, a background in software development with a specialisation in Microsoft products and technologies and a solid knowledge and experience in Microsoft SharePoint Products and Technologies. He started as a COBOL developer on a mainframe environment and grew into software development for Windows platforms. Participated in projects varying from migrations of existing applications to development of Web applications and Windows applications. Became fascinated by the SharePoint 2007 platform and strongly believed in the added business value of this platform. Is since then fully committed to SharePoint and focuses on SharePoint implementations, migrations, integrations, design and coaching. Stays on top of new developments within the SharePoint technology stack and related technologies.

1 comment

Comments are closed.

%d bloggers like this: