mqsft.windowsserveradmin.psm1

# ==============================================================================
# mqsft.windowsserveradmin.psm1 - AUTO-GENERATED by Create_Module_0_0_7.ps1 v0.0.7
# ------------------------------------------------------------------------------
# Module Version : 1.0.1
# Script Version : 0.0.7
# Built : 2026-02-24 17:37:09
# Source : C:\Modules\functions\mqsft.windowsserveradmin
#
# DO NOT EDIT THIS FILE DIRECTLY.
# Edit source files in C:\Modules\functions\mqsft.windowsserveradmin and re-run Create_Module_0_0_7.ps1.
# ==============================================================================

Set-StrictMode -Version Latest

# --- Source: Get-LocalAdministrators.ps1 ---------------------------------
function Get-LocalAdministrators {

    <#

    .SYNOPSIS

        Retrieves members of the local Administrators group with detailed information.

    

    .DESCRIPTION

        Enumerates all members of the local Administrators group including users, domain users,

        groups, and orphaned SIDs. Provides flexible output formats for different use cases.

    

    .PARAMETER OutputFormat

        Format for displaying results. Options: Table, List, Grid, CSV, JSON, Object

        Default is Table.

    

    .PARAMETER ExportPath

        Path to export results. File extension determines format (.csv or .json)

    

    .PARAMETER IncludeOrphaned

        Include orphaned SIDs in the output. Default is $true.

    

    .PARAMETER ComputerName

        Remote computer name to query. Default is local computer.

    

    .EXAMPLE

        Get-LocalAdministrators

        

    .EXAMPLE

        Get-LocalAdministrators -OutputFormat List

        

    .EXAMPLE

        Get-LocalAdministrators -ExportPath "C:\admins.csv"

        

    .EXAMPLE

        Get-LocalAdministrators -OutputFormat JSON -ExportPath "C:\admins.json"

        

    .EXAMPLE

        $admins = Get-LocalAdministrators -OutputFormat Object

        $admins | Where-Object {$_.Status -eq "Orphaned SID"}

    #>


    

    [CmdletBinding()]

    param(

        [Parameter(Mandatory=$false)]

        [ValidateSet('Table', 'List', 'Grid', 'CSV', 'JSON', 'Object')]

        [string]$OutputFormat = 'Table',

        

        [Parameter(Mandatory=$false)]

        [string]$ExportPath,

        

        [Parameter(Mandatory=$false)]

        [bool]$IncludeOrphaned = $true,

        

        [Parameter(Mandatory=$false)]

        [string]$ComputerName = "."

    )

    

    Write-Host "`nRetrieving local administrator group members..." -ForegroundColor Cyan

    

    try {

        # Connect to the Administrators group

        $adminGroup = [ADSI]"WinNT://$ComputerName/Administrators,group"

        $members = $adminGroup.Invoke("Members")

        

        $results = @()

        $count = 0

        

        foreach ($member in $members) {

            $count++

            Write-Progress -Activity "Processing Administrator Members" -Status "Member $count" -PercentComplete (($count / @($members).Count) * 100)

            

            try {

                # Get the ADsPath first

                $adsPath = $member.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $member, $null)

                

                # Create ADSI object from the path

                $user = [ADSI]$adsPath

                

                # Try to get properties using InvokeMember

                $userName = $member.GetType().InvokeMember("Name", 'GetProperty', $null, $member, $null)

                $userClass = $member.GetType().InvokeMember("Class", 'GetProperty', $null, $member, $null)

                

                # Try to get SID

                $sidValue = "Unable to retrieve SID"

                try {

                    $objectSid = $member.GetType().InvokeMember("objectSid", 'GetProperty', $null, $member, $null)

                    if ($objectSid) {

                        $sid = New-Object System.Security.Principal.SecurityIdentifier($objectSid, 0)

                        $sidValue = $sid.Value

                    }

                } catch {

                    # SID retrieval failed, but we still have the name

                }

                

                # Determine account type

                $accountType = switch ($userClass) {

                    'User' { 'Local User' }

                    'Group' { 'Local Group' }

                    'ForeignSecurityPrincipal' { 'Domain Account' }

                    default { $userClass }

                }

                

                $results += [PSCustomObject]@{

                    Name        = $userName

                    AccountType = $accountType

                    Class       = $userClass

                    SID         = $sidValue

                    Status      = "Active"

                    Path        = $adsPath

                    ComputerName = $ComputerName

                }

                

            } catch {

                try {

                    # Fallback: try to get path and extract info

                    $path = $member.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $member, $null)

                    

                    # Extract the last part of the path

                    $pathParts = $path -split '/'

                    $lastPart = $pathParts[-1]

                    

                    # Check if it's a SID format

                    if ($lastPart -match '^S-\d-\d+-(\d+-)*\d+$') {

                        try {

                            # Try to resolve the SID to a name

                            $sidObject = New-Object System.Security.Principal.SecurityIdentifier($lastPart)

                            $resolvedAccount = $sidObject.Translate([System.Security.Principal.NTAccount])

                            $resolvedName = $resolvedAccount.Value

                            

                            $results += [PSCustomObject]@{

                                Name        = $resolvedName

                                AccountType = "Resolved Account"

                                Class       = "Resolved"

                                SID         = $lastPart

                                Status      = "Resolved from SID"

                                Path        = $path

                                ComputerName = $ComputerName

                            }

                        } catch {

                            # Truly orphaned SID

                            if ($IncludeOrphaned) {

                                $results += [PSCustomObject]@{

                                    Name        = "Orphaned Account"

                                    AccountType = "Orphaned"

                                    Class       = "Orphaned"

                                    SID         = $lastPart

                                    Status      = "Orphaned SID"

                                    Path        = $path

                                    ComputerName = $ComputerName

                                }

                            }

                        }

                    } else {

                        # Try to extract name from the path or use the last part

                        $results += [PSCustomObject]@{

                            Name        = $lastPart

                            AccountType = "Unknown"

                            Class       = "Unknown"

                            SID         = "Unable to retrieve SID"

                            Status      = "Extracted from path"

                            Path        = $path

                            ComputerName = $ComputerName

                        }

                    }

                } catch {

                    $results += [PSCustomObject]@{

                        Name        = "Unable to process"

                        AccountType = "Error"

                        Class       = "Error"

                        SID         = "Unknown"

                        Status      = "Processing Error"

                        Path        = "Unknown"

                        ComputerName = $ComputerName

                    }

                }

            }

        }

        

        Write-Progress -Activity "Processing Administrator Members" -Completed

        

        # Summary statistics

        $totalCount = $results.Count

        $activeCount = ($results | Where-Object {$_.Status -eq "Active"}).Count

        $orphanedCount = ($results | Where-Object {$_.Status -eq "Orphaned SID"}).Count

        $domainCount = ($results | Where-Object {$_.AccountType -eq "Domain Account"}).Count

        $localUserCount = ($results | Where-Object {$_.AccountType -eq "Local User"}).Count

        $groupCount = ($results | Where-Object {$_.AccountType -like "*Group*"}).Count

        

        Write-Host "`nSummary:" -ForegroundColor Green

        Write-Host " Total Members: $totalCount"

        Write-Host " Active Accounts: $activeCount" -ForegroundColor Green

        Write-Host " Local Users: $localUserCount"

        Write-Host " Groups: $groupCount"

        Write-Host " Domain Accounts: $domainCount"

        if ($orphanedCount -gt 0) {

            Write-Host " Orphaned SIDs: $orphanedCount" -ForegroundColor Yellow

        }

        Write-Host ""

        

        # Handle export if specified

        if ($ExportPath) {

            $extension = [System.IO.Path]::GetExtension($ExportPath).ToLower()

            

            switch ($extension) {

                '.csv' {

                    $results | Export-Csv -Path $ExportPath -NoTypeInformation

                    Write-Host "Results exported to: $ExportPath" -ForegroundColor Cyan

                }

                '.json' {

                    $exportData = @{

                        Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

                        ComputerName = $ComputerName

                        Summary = @{

                            TotalMembers = $totalCount

                            ActiveAccounts = $activeCount

                            OrphanedSIDs = $orphanedCount

                            DomainAccounts = $domainCount

                            LocalUsers = $localUserCount

                            Groups = $groupCount

                        }

                        Members = $results

                    }

                    $exportData | ConvertTo-Json -Depth 10 | Out-File -FilePath $ExportPath

                    Write-Host "Results exported to: $ExportPath" -ForegroundColor Cyan

                }

                default {

                    Write-Warning "Unsupported file extension. Using CSV format."

                    $results | Export-Csv -Path $ExportPath -NoTypeInformation

                    Write-Host "Results exported to: $ExportPath" -ForegroundColor Cyan

                }

            }

        }

        

        # Display results based on format

        switch ($OutputFormat) {

            'Table' {

                $results | Select-Object Name, AccountType, SID, Status | Format-Table -AutoSize

            }

            'List' {

                $results | Format-List Name, AccountType, Class, SID, Status, Path

            }

            'Grid' {

                $results | Out-GridView -Title "Local Administrators - $ComputerName"

            }

            'CSV' {

                $results | ConvertTo-Csv -NoTypeInformation | Write-Output

            }

            'JSON' {

                $results | ConvertTo-Json -Depth 10 | Write-Output

            }

            'Object' {

                return $results

            }

        }

        

        # Always return the object for pipeline usage

        if ($OutputFormat -ne 'Object') {

            return $results

        }

        

    } catch {

        Write-Error "Failed to retrieve administrator group members: $_"

        return $null

    }

}



# Example usage:

 Get-LocalAdministrators

# Get-LocalAdministrators -OutputFormat List

# Get-LocalAdministrators -OutputFormat Grid

# Get-LocalAdministrators -ExportPath "C:\admins.csv"

# Get-LocalAdministrators -OutputFormat JSON -ExportPath "C:\admins.json"

# $admins = Get-LocalAdministrators -OutputFormat Object

# $admins | Where-Object {$_.Status -eq "Orphaned SID"} | Format-Table