Public/04_AD_GPO/Get-VBActiveDirectoryInfo.ps1

# ============================================================
# FUNCTION : Get-VBActiveDirectoryInfo
# VERSION : 1.0.2
# CHANGED : 10-04-2026 -- Initial VB-compliant release
# AUTHOR : Vibhu Bhatnagar
# PURPOSE : Collects comprehensive Active Directory information including domain controllers, servers, FSMO roles, users, and security status
# ENCODING : UTF-8 with BOM
# ============================================================

<#
.SYNOPSIS
    Collects comprehensive Active Directory information.
 
.DESCRIPTION
    Retrieves detailed information about the Active Directory environment including domain controllers,
    all Windows servers, FSMO roles, user folder configurations, SYSVOL scripts, privileged user accounts,
    functional levels, and Recycle Bin status.
 
.PARAMETER ComputerName
    Domain Controller to query. Defaults to local machine. Accepts pipeline input.
 
.PARAMETER Credential
    Alternate credentials for the AD query.
 
.EXAMPLE
    Get-VBActiveDirectoryInfo
 
.EXAMPLE
    Get-VBActiveDirectoryInfo -ComputerName DC01
 
.EXAMPLE
    'DC01','DC02' | Get-VBActiveDirectoryInfo -Credential (Get-Credential)
 
.OUTPUTS
    [PSCustomObject]: ComputerName, DomainControllers, AllServers, FSMORoles, UserFolderReport,
    SysvolScripts, PrivilegedUsers, DomainFunctionalLevel, ForestFunctionalLevel, RecycleBinEnabled,
    TombstoneLifetime, TotalADUsers, ADRecyclebin, Status, CollectionTime
 
.NOTES
    Version : 1.0.2
    Author : Vibhu Bhatnagar
    Modified : 10-04-2026
    Category : AD / GPO
#>


function Get-VBActiveDirectoryInfo {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Name', 'Server', 'Host')]
        [string[]]$ComputerName = $env:COMPUTERNAME,
        [PSCredential]$Credential
    )
    begin {
        Import-Module ActiveDirectory -ErrorAction Stop
        Import-Module GroupPolicy -ErrorAction Stop
    }



    process {
        foreach ($computer in $ComputerName) {
            try {
                # Step 1 -- Prepare AD query parameters
                $AdParams = @{}
                if ($computer -ne $env:COMPUTERNAME) {
                    $AdParams['Server'] = $computer
                }
                if ($Credential) {
                    $AdParams['Credential'] = $Credential
                }

                # Step 2 -- Retrieve domain controllers
                $DomainControllers = Get-ADDomainController -Filter * @AdParams |
                    Select-Object Name, Domain, Forest, OperationMasterRoles, IsReadOnly

                # Step 3 -- Retrieve all Windows servers
                $AllServers = Get-ADComputer -Filter { OperatingSystem -Like "Windows Server*" } -Property * @AdParams |
                    Select-Object Name, IPv4Address, OperatingSystem, OperatingSystemVersion, Enabled, LastLogonDate, WhenCreated |
                    Sort-Object OperatingSystemVersion

                # Step 4 -- Retrieve FSMO roles
                $FsmoRoles = [PSCustomObject]@{
                    InfrastructureMaster = (Get-ADDomain @AdParams).InfrastructureMaster
                    PDCEmulator          = (Get-ADDomain @AdParams).PDCEmulator
                    RIDMaster            = (Get-ADDomain @AdParams).RIDMaster
                    DomainNamingMaster   = (Get-ADForest @AdParams).DomainNamingMaster
                    SchemaMaster         = (Get-ADForest @AdParams).SchemaMaster
                }

                # Step 5 -- Get functional levels
                $DomainFunctionalLevel = (Get-ADDomain @AdParams).DomainMode
                $ForestFunctionalLevel = (Get-ADForest @AdParams).ForestMode

                # Step 6 -- Check Recycle Bin status
                $RecycleBinEnabled = (Get-ADOptionalFeature -Filter { Name -eq 'Recycle Bin Feature' } @AdParams).EnabledScopes.Count -gt 0

                # Step 7 -- Get tombstone lifetime
                $RootDse = Get-ADRootDSE @AdParams
                $ConfigContext = $RootDse.configurationNamingContext
                $TombstoneLifetime = (Get-ADObject -Identity "CN=Directory Service,CN=Windows NT,CN=Services,$ConfigContext" -Properties tombstoneLifetime @AdParams).tombstoneLifetime

                # Step 8 -- Retrieve all users and build folder report
                $Users = Get-ADUser -Filter * -Properties SamAccountName, ProfilePath, ScriptPath, homeDrive, homeDirectory @AdParams

                $UserFolderReport = foreach ($user in $Users) {
                    [PSCustomObject]@{
                        SamAccountName = $user.SamAccountName
                        ProfilePath    = if ([string]::IsNullOrEmpty($user.ProfilePath)) { "N/A" } else { $user.ProfilePath }
                        LogonScript    = if ([string]::IsNullOrEmpty($user.ScriptPath)) { "N/A" } else { $user.ScriptPath }
                        HomeDrive      = if ([string]::IsNullOrEmpty($user.homeDrive)) { "N/A" } else { $user.homeDrive }
                        HomeDirectory  = if ([string]::IsNullOrEmpty($user.homeDirectory)) { "N/A" } else { $user.homeDirectory }
                    }
                }

                $TotalUsers = $Users.Count

                # Step 9 -- Retrieve SYSVOL scripts
                $ScriptBlock = {
                    if (Test-Path -Path "C:\Windows\SYSVOL\sysvol") {
                        $FolderPath = (Get-ChildItem "C:\Windows\SYSVOL\sysvol" | Where-Object { $_.PSIsContainer } | Select-Object -First 1).FullName
                        Get-ChildItem -Recurse -Path "$FolderPath" -ErrorAction SilentlyContinue |
                            Where-Object { $_.Extension -in ".bat", ".cmd", ".ps1", ".vbs", ".exe", ".msi" } |
                            Select-Object FullName, Length, LastWriteTime
                    }
                }

                if ($computer -eq $env:COMPUTERNAME) {
                    $SysvolScripts = & $ScriptBlock
                } else {
                    $SysvolScripts = Invoke-Command -ComputerName $computer -ScriptBlock $ScriptBlock -Credential $Credential -ErrorAction SilentlyContinue
                }

                # Step 10 -- Retrieve privileged users
                $PrivilegedUsers = @()

                $GroupNames = 'Enterprise Admins', 'Domain Admins', 'Schema Admins'
                foreach ($groupName in $GroupNames) {
                    try {
                        $Members = Get-ADGroupMember -Identity $groupName -Recursive -ErrorAction SilentlyContinue @AdParams | Sort-Object Name
                        $PrivilegedUsers += foreach ($member in $Members) {
                            Get-ADUser -Identity $member.SID -Properties * @AdParams |
                                Select-Object Name, @{Name = 'Group'; Expression = { $groupName } }, WhenCreated, LastLogonDate, SamAccountName
                        }
                    } catch {
                        # Group not found or inaccessible
                    }
                }

                # Step 11 -- Check Recycle Bin status with emoji replacement
                $RecycleBinStatus = if ($RecycleBinEnabled) { "ENABLED" } else { "DISABLED" }

                # Step 12 -- Return comprehensive object
                [PSCustomObject]@{
                    ComputerName          = $computer
                    DomainControllers     = $DomainControllers
                    AllServers            = $AllServers
                    FSMORoles             = $FsmoRoles
                    UserFolderReport      = $UserFolderReport
                    SysvolScripts         = $SysvolScripts
                    PrivilegedUsers       = $PrivilegedUsers
                    DomainFunctionalLevel = $DomainFunctionalLevel
                    ForestFunctionalLevel = $ForestFunctionalLevel
                    RecycleBinEnabled     = $RecycleBinEnabled
                    TombstoneLifetime     = $TombstoneLifetime
                    TotalADUsers          = $TotalUsers
                    ADRecyclebin          = $RecycleBinStatus
                    Status                = 'Success'
                    CollectionTime        = (Get-Date).ToString('dd-MM-yyyy HH:mm:ss')
                }
            } catch {
                [PSCustomObject]@{
                    ComputerName = $computer
                    Error        = $_.Exception.Message
                    Status       = 'Failed'
                    CollectionTime = (Get-Date).ToString('dd-MM-yyyy HH:mm:ss')
                }
            }
        }
    }
}