functions/get-adgroupreport.ps1


<#
Get group membership report
#>

Function Get-ADGroupReport {
    [cmdletbinding()]
    [OutputType("ADGroupReport")]
    Param(
        [parameter(Position = 0, HelpMessage = "Enter an AD Group name. Wildcards are allowed.")]
        [validatenotnullorEmpty()]
        [string]$Name = "*",
        [Parameter(HelpMessage = "Enter the distinguished name of the top level container or organizational unit.")]
        [ValidateScript( {
            $testDN = $_
            Try {
                [void](Get-ADObject -Identity $_ -ErrorAction Stop)
                $True
            }
            Catch {
                Write-Warning "Failed to verify $TestDN as a valid searchbase."
                Throw $_.Exception.message
                $False
            }
            })]
        [string]$SearchBase,
        [Parameter(HelpMessage = "Filter on the group category")]
        [ValidateSet("All", "Distribution", "Security")]
        [string]$Category = "All",
        [Parameter(HelpMessage = "Filter on group scope")]
        [ValidateSet("Any", "DomainLocal", "Global", "Universal")]
        [string]$Scope = "Any",
        [Parameter(HelpMessage="Exclude BuiltIn and Users")]
        [switch]$ExcludeBuiltIn,
        [Parameter(HelpMessage = "Specify a domain controller to query for a list of domain controllers.")]
        [alias("dc", "domaincontroller")]
        [string]$Server,
        [Parameter(HelpMessage = "Specify an alternate credential. This will be used to query the domain and all domain controllers.")]
        [alias("RunAs")]
        [PSCredential]$Credential
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
        #set some default parameter values
        $params = "Credential", "Server"

        ForEach ($param in $params) {
            if ($PSBoundParameters.ContainsKey($param)) {
                Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Adding 'Get-AD*:$param' to script PSDefaultParameterValues"
                $script:PSDefaultParameterValues["Get-AD*:$param"] = $PSBoundParameters.Item($param)
            }
        } #foreach

        if ($ExcludeBuiltIn) {
            Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Excluding CN=Users and CN=BuiltIn"
            $Exclude = {$_.DistinguishedName -notMatch "CN\=(Users)|(BuiltIn)"}
        }
        else {
            #Exclude these items using late filtering to keep the AD filter from getting out of control
            $Exclude ={ @("Domain Users","Domain Computers", "Domain Guests") -notcontains $_.name}
        }

        $filter = "Name -like '$name'"
        if ($Category -ne "All") {
            $filter += " -AND GroupCategory -eq '$Category'"
        }
        if ($scope -ne "Any") {
            $filter += " -AND GroupScope -eq '$Scope'"
        }
        $get = @{
            Filter      = $filter
            Properties  = @("Description", "Created", "Modified","ManagedBy")
            ErrorAction = "Stop"
        }

        if ($SearchBase) {
            Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Searching for group(s) under $SearchBase"
            $get.Add("Searchbase", $SearchBase)
        }

    } #begin

    Process {
        if ($PSCmdlet.ParameterSetName -eq 'id') {
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting group $Identity"
        }
        else {
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Searching for groups with filter $filter"
        }

        Try {
            $group = Get-ADGroup @get | Where-Object $Exclude
            if ($group) {
                foreach ($item in $Group ) {

                    #get group members recursively
                    $Members =Get-ADGroupUser -name $item.distinguishedName

                    [PSCustomObject]@{
                        PSTypeName        = "ADGroupReport"
                        DistinguishedName = $item.DistinguishedName
                        Name              = $item.Name
                        Category          = $item.GroupCategory
                        Scope             = $item.GroupScope
                        Description       = $item.Description
                        Branch            = (Split-DistinguishedName -dn $item.DistinguishedName).branchdn
                        Created           = $item.Created
                        Modified          = $item.Modified
                        Members           = $members
                        ManagedBy         = $item.ManagedBy
                    }
                } #foreach item
            } #if $group
            else {
                Write-Warning "No matching groups found."
            }
        } #try
        Catch {
            Write-Warning $_.Exception.Message
        }
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"

    } #end

} #close Get-ADGroupReport

<#
These have been exported to a types file
Update-TypeData -TypeName "ADGroupReport" -MemberType AliasProperty -MemberName DN -Value DistinguishedName -force
Update-TypeData -TypeName "ADGroupReport" -MemberType ScriptProperty -MemberName MemberCount -Value {($this.members | Measure-Object).Count} -force
Update-TypeData -TypeName "ADGroupReport" -MemberType ScriptProperty -MemberName Age -value ({New-Timespan -Start $this.Modified -end (Get-Date)})
#>