Public/activedirectory/Get-ADGroupInventory.ps1
|
#Requires -Version 5.1 function Get-ADGroupInventory { <# .SYNOPSIS Inventories Active Directory groups with member count and metadata .DESCRIPTION Retrieves all Active Directory groups and returns audit-ready objects including member count, scope, category, and organizational unit path extracted from the distinguished name. By default only groups with at least one member are returned. .PARAMETER SearchBase The distinguished name of the OU to search. Defaults to the entire domain root. .PARAMETER Server The Active Directory Domain Services instance (domain controller) to connect to. .PARAMETER Credential The PSCredential object used to authenticate the AD query. .PARAMETER IncludeEmpty When specified, includes groups with zero members in the output. By default only groups with at least one member are returned. .EXAMPLE Get-ADGroupInventory Returns all non-empty AD groups in the current domain sorted by name. .EXAMPLE Get-ADGroupInventory -SearchBase 'OU=Groups,DC=corp,DC=local' -Server 'DC01' Returns non-empty groups from a specific OU targeting a specific domain controller. .EXAMPLE Get-ADGroupInventory -IncludeEmpty -Credential (Get-Credential) Returns all groups including empty ones using alternate credentials. .OUTPUTS PSWinOps.ADGroupInventory Returns objects with Name, SamAccountName, GroupScope, GroupCategory, MemberCount, Description, OrganizationalUnit, and Timestamp properties. .NOTES Author: Franck SALLET Version: 1.0.0 Last Modified: 2026-04-04 Requires: PowerShell 5.1+ / Windows only Requires: ActiveDirectory module (RSAT) .LINK https://github.com/k9fr4n/PSWinOps .LINK https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-adgroup #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$SearchBase, [Parameter()] [ValidateNotNullOrEmpty()] [string]$Server, [Parameter()] [ValidateNotNull()] [System.Management.Automation.PSCredential]$Credential, [Parameter()] [switch]$IncludeEmpty ) Write-Verbose -Message "[$($MyInvocation.MyCommand)] Starting AD group inventory" try { Import-Module -Name 'ActiveDirectory' -ErrorAction Stop -Verbose:$false } catch { Write-Error -Message "[$($MyInvocation.MyCommand)] ActiveDirectory module is not available. Install RSAT: $_" return } $adGroupParams = @{ Filter = '*' Properties = @( 'Name' 'SamAccountName' 'GroupScope' 'GroupCategory' 'DistinguishedName' 'Member' 'Description' ) ErrorAction = 'Stop' } if ($PSBoundParameters.ContainsKey('SearchBase')) { $adGroupParams['SearchBase'] = $SearchBase } if ($PSBoundParameters.ContainsKey('Server')) { $adGroupParams['Server'] = $Server } if ($PSBoundParameters.ContainsKey('Credential')) { $adGroupParams['Credential'] = $Credential } try { $adGroups = Get-ADGroup @adGroupParams } catch { Write-Error -Message "[$($MyInvocation.MyCommand)] Failed to query Active Directory: $_" return } if (-not $adGroups) { Write-Warning -Message "[$($MyInvocation.MyCommand)] No groups matched the specified criteria" return } $queryTimestamp = Get-Date -Format 'o' $resultList = [System.Collections.Generic.List[PSCustomObject]]::new() foreach ($group in $adGroups) { [int]$memberCount = 0 if ($group.Member) { $memberCount = $group.Member.Count } if (-not $IncludeEmpty -and $memberCount -eq 0) { continue } $ouPath = $null if ($group.DistinguishedName) { $dnParts = $group.DistinguishedName -split '(?<!\\),', 2 if ($dnParts.Count -gt 1) { $ouPath = $dnParts[1] } } $entry = [PSCustomObject]@{ PSTypeName = 'PSWinOps.ADGroupInventory' Name = $group.Name SamAccountName = $group.SamAccountName GroupScope = [string]$group.GroupScope GroupCategory = [string]$group.GroupCategory MemberCount = $memberCount Description = $group.Description OrganizationalUnit = $ouPath Timestamp = $queryTimestamp } $resultList.Add($entry) } $resultList | Sort-Object -Property 'Name' Write-Verbose -Message "[$($MyInvocation.MyCommand)] Completed - $($resultList.Count) group(s) returned" } |