Public/Export-ADUserReport.ps1
|
function Export-ADUserReport { <# .SYNOPSIS Generates a comprehensive Active Directory user report in HTML or CSV format. .DESCRIPTION Exports AD user data with flexible filtering and multiple output formats. Useful for audits, compliance reviews, and management reporting. Report includes: name, title, department, email, last logon, account status, password last set, group memberships, and manager. .PARAMETER SearchBase The OU Distinguished Name to scope the search. Defaults to the entire domain. .PARAMETER Filter AD filter string. Defaults to all enabled users with email addresses. .PARAMETER IncludeDisabled Include disabled accounts in the report. .PARAMETER OutputFormat Output format: HTML, CSV, or Both. Defaults to HTML. .PARAMETER OutputPath Directory to save the report. Defaults to current directory. .PARAMETER DaysInactive Flag users who haven't logged in within this many days. Defaults to 90. .EXAMPLE Export-ADUserReport -OutputFormat HTML Generates an HTML report of all enabled users to the current directory. .EXAMPLE Export-ADUserReport -SearchBase "OU=Sales,DC=contoso,DC=com" -OutputFormat Both -DaysInactive 60 Reports on Sales OU users, flagging those inactive for 60+ days, in both formats. .EXAMPLE Export-ADUserReport -IncludeDisabled -OutputPath "\\server\reports" Full user report including disabled accounts, saved to a file share. .NOTES Requires: ActiveDirectory module, read access to AD. #> [CmdletBinding()] param( [string]$SearchBase, [string]$Filter = "Enabled -eq `$true", [switch]$IncludeDisabled, [ValidateSet('HTML', 'CSV', 'Both')] [string]$OutputFormat = 'HTML', [string]$OutputPath = '.', [int]$DaysInactive = 90 ) begin { Import-Module ActiveDirectory -ErrorAction Stop if (-not (Test-Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null } $reportDate = Get-Date -Format 'yyyyMMdd-HHmmss' $inactiveThreshold = (Get-Date).AddDays(-$DaysInactive) if ($IncludeDisabled) { $Filter = '*' } } process { # Build Get-ADUser parameters $adParams = @{ Filter = $Filter Properties = @( 'DisplayName', 'Title', 'Department', 'Company', 'EmailAddress', 'LastLogonDate', 'PasswordLastSet', 'PasswordNeverExpires', 'WhenCreated', 'MemberOf', 'Manager', 'Enabled', 'LockedOut', 'HomeDirectory', 'Description' ) } if ($SearchBase) { $adParams['SearchBase'] = $SearchBase } Write-Verbose "Querying Active Directory..." $users = Get-ADUser @adParams Write-Verbose "Processing $($users.Count) users..." $report = foreach ($user in $users) { $managerName = if ($user.Manager) { try { (Get-ADUser $user.Manager).Name } catch { $user.Manager } } else { '' } $groupList = ($user.MemberOf | ForEach-Object { try { (Get-ADGroup $_).Name } catch { $_ } }) -join '; ' $isInactive = $user.LastLogonDate -and ($user.LastLogonDate -lt $inactiveThreshold) $neverLoggedOn = -not $user.LastLogonDate [PSCustomObject]@{ SAMAccountName = $user.SAMAccountName DisplayName = $user.DisplayName Title = $user.Title Department = $user.Department Company = $user.Company Email = $user.EmailAddress Enabled = $user.Enabled LockedOut = $user.LockedOut LastLogon = $user.LastLogonDate Inactive = $isInactive NeverLoggedOn = $neverLoggedOn PasswordLastSet = $user.PasswordLastSet PasswordNeverExpires = $user.PasswordNeverExpires Created = $user.WhenCreated Manager = $managerName Groups = $groupList HomeDirectory = $user.HomeDirectory Description = $user.Description } } # Output to requested format(s) if ($OutputFormat -in @('CSV', 'Both')) { $csvFile = Join-Path $OutputPath "AD-UserReport-$reportDate.csv" $report | Export-Csv -Path $csvFile -NoTypeInformation Write-Verbose "CSV saved: $csvFile" } if ($OutputFormat -in @('HTML', 'Both')) { $htmlFile = Join-Path $OutputPath "AD-UserReport-$reportDate.html" $htmlReport = _New-HtmlReport -Title "Active Directory User Report" -Data $report -GeneratedDate (Get-Date) $htmlReport | Out-File -FilePath $htmlFile -Encoding UTF8 Write-Verbose "HTML saved: $htmlFile" } # Return objects to the pipeline $report } } |