ModernActiveDirectoryEnhanced.psm1
|
<# .SYNOPSIS Modern Active Directory HTML Report with End-of-Life Tracking Generates comprehensive, interactive HTML reports for Active Directory analysis including End-of-Life (EoL) tracking for operating systems. .DESCRIPTION The Modern Active Directory Report module creates dynamic, multi-page HTML reports that provide detailed insights into your Active Directory environment. KEY FEATURES: - Interactive HTML interface with dynamic filtering and sorting - Dashboard with visual statistics and trends - User analysis (inactive, locked, expiring passwords, new accounts) - Computer inventory with OS version tracking and EoL status - End-of-Life (EoL) tracking for Windows, Linux, and macOS systems - Group membership analysis - GPO reporting - Organizational Unit (OU) structure - Security analysis (privileged accounts, default passwords) EoL DATABASE: The module includes comprehensive End-of-Life tracking using an external JSON database (eol-database.json) that can be updated independently. Supported systems include: - Windows 10/11 (all releases including LTSC) - Windows Server 2008 through 2025 - Ubuntu LTS, Debian, RHEL, SLES - macOS (recent versions) REQUIREMENTS: - PowerShell 5.1 or later - Active Directory PowerShell module (RSAT-AD-PowerShell) - PSWriteHTML module (auto-installed if missing) - Domain Administrator or Read permissions on AD - EoL-Functions.ps1 and eol-database.json (for EoL tracking) .PARAMETER CompanyLogo URL or UNC path to your company logo (displayed on the left side). Accepts: .PNG, .JPG, .GIF formats Default: GitHub project logo Example: "C:\Logos\MyCompany.png" or "https://example.com/logo.png" .PARAMETER RightLogo URL or UNC path for a secondary logo (displayed on the right side). Useful for department logos, certifications, or partner logos. Default: GitHub project logo .PARAMETER ReportTitle Custom title for the generated report. This title appears at the top of the HTML report. Default: "Active Directory Report" .PARAMETER SavePath Directory path where the HTML report will be saved. The module creates multiple files (HTML, CSS, JS) in this location. Default: $env:TEMP (Windows temporary folder) Note: Ensure write permissions exist for the specified path. .PARAMETER UserInactiveDays Number of days of inactivity after which a user account is flagged as inactive. Users who have not logged in for this many days are highlighted in the report. Default: 90 days Range: 1-365 days recommended .PARAMETER UserCreatedDays Show users created within the last X days. Useful for auditing recent account creation. Default: 7 days .PARAMETER UserPasswordExpireDays Show users whose passwords will expire within X days. Helps with proactive password management and user notification. Default: 7 days .PARAMETER MaxSearchObjects Maximum number of AD objects (users/computers) to retrieve. Use lower values for quick testing on large environments. Default: 300 Use -UnlimitedSearch to bypass this limit. .PARAMETER MaxSearchGroups Maximum number of AD groups to retrieve. Default: 300 Use -UnlimitedSearch to bypass this limit. .PARAMETER OUSearchScope Depth of Organizational Unit (OU) scanning. - "OneLevel": Scan only direct child OUs (faster) - "Base": Scan only the base OU - "Subtree": Scan all nested OUs (comprehensive but slower) Default: "OneLevel" .PARAMETER UnlimitedSearch Remove all search limits and retrieve ALL AD objects. Warning: Can be slow on large environments (10K+ objects). Internally sets MaxSearchObjects=300000 and MaxSearchGroups=100000. .PARAMETER LimitedView Security filter that excludes privileged accounts from the report (enabled by default). When enabled (default): - EXCLUDES users with AdminCount=1 (Domain Admins, Enterprise Admins, etc.) - EXCLUDES privileged groups (Domain Admins, Schema Admins, etc.) - Shows only regular users and non-privileged groups Purpose: - Prevent exposure of administrative accounts in shared reports - Comply with security best practices - Reduce risk if the report falls into the wrong hands To include ALL accounts and sensitive objects: - Use -ShowSensitiveObjects (overrides LimitedView and unlocks DC, GPO-DC sections, and privileged groups) - Or set -LimitedView:$false (includes privileged users/groups without unlocking extra sections) Default: $true (secure by default) .PARAMETER ShowSensitiveObjects Include ALL sensitive and privileged objects in the report and unlock additional sections. When enabled, the following objects — excluded by default — become visible: - Users with AdminCount=1 (Domain Admins, Enterprise Admins, etc.) - Privileged groups (Domain Admins, Schema Admins, Builtin groups, etc.) - Domain Controllers (normally excluded from the computer inventory) - GPO linked to the Domain Controllers OU (dedicated section unlocked) Also overrides LimitedView. Use this flag when performing a full security audit or Tier-0 review. Note: Use -LimitedView:$false if you only want to include privileged users/groups without unlocking the DC and GPO-DC sections. .PARAMETER SinglePageReport Generate a single-page HTML report instead of a multi-page report. Recommended only for small environments (fewer than 5000 objects). Faster to load but less organized for large datasets. .PARAMETER ShowEoLOverview Display the End-of-Life overview section in the report. Shows a summary of systems approaching or past their EoL dates. .PARAMETER DaysBeforeEoL Number of days before End-of-Life to trigger a warning status. Systems within this threshold are shown as "J-XX" (e.g. J-90, J-60). Default: 90 days STATUS INDICATORS: - "Supported" (Green): More than X days remaining before EoL - "J-XX" (Orange): Warning - fewer than X days until EoL - "EOL" (Red): Past End-of-Life date - "Unknown" (Gray): OS not found in the EoL database .PARAMETER AdminInactivityThreshold Number of days of inactivity after which an admin account triggers a security alert. ANSSI recommends flagging admin accounts inactive for more than 90 days. Default: 90 days .PARAMETER UserInactivityThreshold Number of days of inactivity after which a standard user account triggers a security alert. ANSSI recommends flagging user accounts inactive for more than 180 days. Default: 180 days .PARAMETER DisabledAccountsThreshold Percentage of disabled accounts above which a security alert is triggered. ANSSI recommends investigating if disabled accounts exceed 30% of total accounts. Default: 30 .PARAMETER EmptyGroupsThreshold Percentage of empty groups above which a security alert is triggered. A high number of empty groups may indicate poor group lifecycle management. Default: 20 .PARAMETER PasswordNeverExpiresThreshold Percentage of accounts with password set to never expire above which a security alert is triggered. ANSSI recommends keeping this below 5% of total accounts. Default: 5 .PARAMETER ComputerInactivityThreshold Number of days of inactivity after which a computer account triggers a security alert. ANSSI recommends flagging computer accounts inactive for more than 90 days. Default: 90 days .PARAMETER PreCheck Run environment validation only, without generating the full report. Verifies AD connectivity, required modules, account permissions, and estimates execution time. Useful before running a full report on large or unknown environments. .EXAMPLE Get-MADReport Basic usage - Creates a report with default settings (300 objects max). Output: Multi-page HTML report saved to $env:TEMP folder. .EXAMPLE Get-MADReport -UnlimitedSearch -SavePath "C:\Reports" Full environment scan with unlimited objects. Report saved to C:\Reports folder. Recommended for comprehensive audits. .EXAMPLE Get-MADReport -UnlimitedSearch -SavePath "C:\Reports" -ReportTitle "Q1 2026 Audit" Complete scan with custom report title. Useful for quarterly compliance reporting. .EXAMPLE Get-MADReport -CompanyLogo "C:\Logos\Acme.png" -RightLogo "C:\Logos\ISO27001.png" -ReportTitle "ACME Corp - IT Infrastructure" Branded report with custom logos and title. Perfect for executive presentations. .EXAMPLE Get-MADReport -UserInactiveDays 180 -UserPasswordExpireDays 14 -UserCreatedDays 30 Custom thresholds for user analysis: - Flag users inactive for 180+ days - Show passwords expiring within 14 days - Show users created in last 30 days .EXAMPLE Get-MADReport -MaxSearchObjects 50 -MaxSearchGroups 20 -SavePath "C:\Test" Quick test on large environment. Limits to 50 users/computers and 20 groups for fast generation. .EXAMPLE Get-MADReport -UnlimitedSearch -ShowSensitiveObjects -OUSearchScope Subtree Comprehensive security audit: - Unlimited search - Include ALL sensitive objects: privileged accounts, DC, GPO-DC sections - Deep OU scanning .EXAMPLE Get-MADReport -SinglePageReport -MaxSearchObjects 1000 -SavePath "C:\Reports\QuickView.html" Single-page report for small environment. All data in one HTML file (up to 1000 objects). .EXAMPLE Get-MADReport -DaysBeforeEoL 120 -SavePath "C:\EoL_Reports" Focus on End-of-Life tracking with 120-day warning threshold. Highlights systems approaching EoL within 4 months. .EXAMPLE Get-MADReport -UnlimitedSearch -ShowEoLOverview -SavePath "C:\Compliance" Full compliance report with EoL overview section. Includes detailed breakdown of OS versions and support status. .NOTES File Name : ModernActiveDirectoryEnhanced.psm1 Author : JCh Labs Prerequisite : PowerShell 5.1+, AD Module, PSWriteHTML Version : 2.0.0 PROJECT INFORMATION: - Repository : https://github.com/JCh-Labs/ModernActiveDirectoryEnhanced - License : Use at your own risk - Last Updated : February 2026 PERFORMANCE TIPS: - Use MaxSearchObjects/MaxSearchGroups for large environments (10K+ objects) - OneLevel OU search is faster than Subtree - Single-page reports load faster but are harder to navigate - Schedule reports during off-hours for minimal AD impact END-OF-LIFE DATABASE: - Database File: eol-database.json (must be in same folder as .psm1) - Functions File: EoL-Functions.ps1 (must be in same folder as .psm1) - Update: Database can be updated via Update-EoLFromAPI cmdlet - Coverage: 100+ OS versions (Windows, Linux, macOS) TROUBLESHOOTING: - If EoL data is missing: Ensure eol-database.json and EoL-Functions.ps1 are in the module folder - Slow performance: Reduce MaxSearchObjects or use OneLevel OU search - Module not found: Run 'Import-Module ModernActiveDirectory -Force' - PSWriteHTML missing: Module will auto-install in CurrentUser scope on first run (requires internet access to PSGallery) SECURITY NOTES: - Requires read access to Active Directory - No modifications are made to AD (read-only operations) - Generated reports may contain sensitive data - secure appropriately - Review report content before sharing outside IT department .LINK https://github.com/JCh-Labs/ModernActiveDirectoryEnhanced .LINK https://endoflife.date .OUTPUTS HTML Files The module generates multiple files in the SavePath directory: - Main HTML report (multi-page or single-page) - CSS stylesheets - JavaScript files for interactivity - Embedded data for charts and tables Console Output Progress messages showing: - Module loading status - EoL database status - Data collection progress - Object counts and statistics - Report generation status - Final report location #> function Get-MADReport{ [CmdletBinding()] param ( [bool]$LimitedView = $true, #Company logo that will be displayed on the left, can be URL or UNC [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter URL or UNC path to Company Logo")] [String]$CompanyLogo = "https://raw.githubusercontent.com/JCh-Labs/ModernActiveDirectoryEnhanced/main/Pictures/MAD_Logo.png", #Logo that will be on the right side, UNC or URL [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter URL or UNC path for Side Logo")] [String]$RightLogo = "https://raw.githubusercontent.com/JCh-Labs/ModernActiveDirectoryEnhanced/main/Pictures/MAD_RightLogo-1.png", #Title of generated report [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter desired title for report")] [String]$ReportTitle = "Active Directory Report", #Location the report will be saved [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter desired directory path to save the report; Default: Windows Temp folder")] [String]$SavePath = $env:TEMP, #Find users that have not logged in X Amount of days, this sets the days [Parameter(ValueFromPipeline = $true, HelpMessage = "Users that have not logged on in more than [X] days. amount of days; Default: 90")] $UserInactiveDays = 90, #Get users who have been created in X amount of days and less [Parameter(ValueFromPipeline = $true, HelpMessage = "Users that have been created within [X] amount of days; Default: 30")] $UserCreatedDays = 30, #Get users whos passwords expire in less than X amount of days [Parameter(ValueFromPipeline = $true, HelpMessage = "Users password expires within [X] amount of days; Default: 30")] $UserPasswordExpireDays = 30, #MAX Users/Computers to search (lower for quick tests on large environments) [Parameter(ValueFromPipeline = $true, HelpMessage = "Max users and computers to retrieve; Default: 1000")] $MaxSearchObjects = 1000, #MAX Groups to search (lower for quick tests on large environments) [Parameter(ValueFromPipeline = $true, HelpMessage = "Max groups to retrieve; Default: 1000")] $MaxSearchGroups = 1000, #OU Search scope: Onelevel (direct children only), Base, or Subtree (all nested OUs) [Parameter(ValueFromPipeline = $true, HelpMessage = "OU search scope - Onelevel (faster), Base, or Subtree (comprehensive); Default: Onelevel")] [ValidateSet("Onelevel","Base","Subtree")]$OUSearchScope = 'Onelevel', #Remove all search limits and retrieve ALL AD objects. Can be slow on large environments. [Parameter(ValueFromPipeline = $true, HelpMessage = "Remove search limits; internally sets MaxSearchObjects=300000 and MaxSearchGroups=100000")] [switch]$UnlimitedSearch, #Include ALL sensitive/privileged objects (admin accounts, privileged groups, Domain Controllers, GPO-DC). #Overrides LimitedView. Unlocks additional report sections. [Parameter(ValueFromPipeline = $true, HelpMessage = "Include privileged accounts, DC, and GPO-DC sections. Overrides LimitedView.")] [switch]$ShowSensitiveObjects, #Generate a single-page HTML report. Recommended only for small environments (<5000 objects). [Parameter(ValueFromPipeline = $true, HelpMessage = "Generate a single-page HTML report instead of multi-page; recommended for small environments only")] [switch]$SinglePageReport, [switch]$ShowEoLOverview, #Nombre de jours pour identifier les objets recemment crees (utilisateurs et ordinateurs) [Parameter(ValueFromPipeline = $true, HelpMessage = "Days window to flag recently created users and computers; Default: 30")] [int]$RecentObjectsDays = 30, #Number of days before End of Life to trigger J-XX warning status [Parameter(ValueFromPipeline = $true, HelpMessage = "Number of days before EoL to show warning status; Default: 90")] [int]$DaysBeforeEoL = 90, # === SEUILS D'ALERTE SÉCURITÉ (recommandations ANSSI) === #Seuil alerte : Comptes administrateurs inactifs (jours) [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if admin accounts inactive for X days; ANSSI recommends 90; Default: 90")] [int]$AdminInactivityThreshold = 90, #Seuil alerte : Comptes utilisateurs inactifs (jours) [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if user accounts inactive for X days; ANSSI recommends 180; Default: 180")] [int]$UserInactivityThreshold = 180, #Seuil alerte : Pourcentage de comptes désactivés [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if disabled accounts exceed X percent; ANSSI recommends 30; Default: 30")] [int]$DisabledAccountsThreshold = 30, #Seuil alerte : Groupes vides [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if empty groups exceed X percent; Default: 20")] [int]$EmptyGroupsThreshold = 20, #Seuil alerte : Mots de passe n'expirant jamais [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if password never expires accounts exceed X percent; ANSSI recommends 5; Default: 5")] [int]$PasswordNeverExpiresThreshold = 5, #Seuil alerte : Ordinateurs inactifs (jours) [Parameter(ValueFromPipeline = $true, HelpMessage = "Alert if computers inactive for X days; ANSSI recommends 90; Default: 90")] [int]$ComputerInactivityThreshold = 90, #Run PreCheck only to verify environment before generating full report [Parameter(ValueFromPipeline = $true, HelpMessage = "Run PreCheck only to verify AD environment, modules, permissions, and estimate execution time")] [switch]$PreCheck, #Ouvre le rapport dans le navigateur apres generation # ANOMALIE4 FIX : [switch]$x = $true est invalide en PS5.1 (defaut garanti $false # pour les switch). On utilise [bool] pour permettre un vrai defaut $true. [Parameter(ValueFromPipeline = $true, HelpMessage = "Open the HTML report in the default browser after generation")] [bool]$ShowReport = $true ) # --- MAD-OSFamilyMap charge en premier — source de vérité unique pour la catégorisation des OS --- $_mad_osfamilymap = Join-Path $PSScriptRoot "MAD-OSFamilyMap.ps1" if (Test-Path $_mad_osfamilymap) { . $_mad_osfamilymap } else { throw "MAD-OSFamilyMap.ps1 introuvable dans $PSScriptRoot" } # --- MAD-Helpers charge ensuite pour rendre Write-Warning-Custom disponible --- $_mad_helpers = Join-Path $PSScriptRoot "MAD-Helpers.ps1" if (Test-Path $_mad_helpers) { . $_mad_helpers } else { throw "MAD-Helpers.ps1 introuvable dans $PSScriptRoot" } # === CHARGEMENT DU MODULE EOL === $EoLModulePath = Join-Path $PSScriptRoot "EoL-Functions.ps1" $EoLDatabaseLoaded = $false if (Test-Path $EoLModulePath) { try { . $EoLModulePath Write-Host "✓ Module EoL-Functions.ps1 chargé" -ForegroundColor Green $EoLDatabaseLoaded = $true } catch { Write-Warning-Custom "Erreur chargement EoL-Functions.ps1 : $($_.Exception.Message)" $EoLDatabaseLoaded = $false } } else { Write-Verbose "Module EoL-Functions.ps1 non trouvé - mode statique" $EoLDatabaseLoaded = $false } # === CHARGEMENT DU MODULE VERSIONING EOL === $EoLVersioningPath = Join-Path $PSScriptRoot "EoL-Versioning.ps1" if (Test-Path $EoLVersioningPath) { try { . $EoLVersioningPath Write-Verbose "✓ Module EoL-Versioning.ps1 chargé" } catch { Write-Warning-Custom "Erreur chargement EoL-Versioning.ps1 : $($_.Exception.Message)" } } else { Write-Verbose "Module EoL-Versioning.ps1 non trouvé - fonctions de versioning indisponibles" } # === CHARGEMENT DU MODULE PRECHECK === $PreCheckModulePath = Join-Path $PSScriptRoot "PreCheck-Functions.ps1" $PreCheckModuleLoaded = $false if (Test-Path $PreCheckModulePath) { try { . $PreCheckModulePath Write-Verbose "✓ Module PreCheck-Functions.ps1 chargé" $PreCheckModuleLoaded = $true } catch { Write-Warning-Custom "Erreur chargement PreCheck-Functions.ps1 : $($_.Exception.Message)" $PreCheckModuleLoaded = $false } } else { Write-Verbose "Module PreCheck-Functions.ps1 non trouvé" $PreCheckModuleLoaded = $false } # $WarningStatusName defini ici dans le psm1 — source de verite unique, plus de dependance a Console-Start $WarningStatusName = "J-$DaysBeforeEoL" #Console start — initialisation uniquement (LimitedView, UnlimitedSearch) . "$PSScriptRoot\MAD-Console-Start.ps1" #endregion ConsoleStart # ============================================================================ # PRECHECK — bloc dans le psm1 pour que le return stoppe reellement l'execution # ============================================================================ if ($PreCheck) { if (-not $PreCheckModuleLoaded) { Write-Error "Le module PreCheck-Functions.ps1 est requis mais n'a pas pu etre charge." Write-Host "Assurez-vous que PreCheck-Functions.ps1 est dans le meme repertoire que ce module." -ForegroundColor Yellow return } Write-Host "" Write-Host "[?] MODE PRE-CHECK ACTIVE" -ForegroundColor Cyan Write-Host "----------------------------------------------------" -ForegroundColor Cyan Write-Host "Verification de l'environnement avant generation du rapport..." -ForegroundColor Gray Write-Host "" # Executer le PreCheck — tout l'affichage se fait via Write-Host dans Invoke-ADReportPreCheck. # Le résultat est stocké dans $script:LastPreCheckResult pour un accès éventuel en script, # mais n'est PAS retourné au pipeline pour éviter le dump automatique en console interactive. # Pour récupérer l'objet : $script:LastPreCheckResult après l'appel. $script:LastPreCheckResult = Invoke-ADReportPreCheck -SavePath $SavePath -ShowDetails return } # ============================================================================ # DÉBUT DE L'EXÉCUTION # ============================================================================ Write-Banner Write-SectionHeader "📋 CONFIGURATION" Write-Info "Domaine cible" $env:USERDNSDOMAIN Write-Info "Utilisateur" $env:USERNAME Write-Info "Chemin de sauvegarde" $SavePath Write-Info "Titre du rapport" $ReportTitle Write-Info "Seuil d'alerte EoL" "$DaysBeforeEoL jours (J-$DaysBeforeEoL)" "Yellow" Write-Info "Fenetre objets recents" "$RecentObjectsDays jours" "White" Write-Info "Recherche limitée" $(if ($UnlimitedSearch) { "Non (recherche complète)" } else { "Oui (max $MaxSearchObjects objets)" }) Write-Host "" # --- Parametres actifs --- Write-Host " Parametres actifs :" -ForegroundColor DarkGray if ($ShowSensitiveObjects.IsPresent) { Write-Host " + ShowSensitiveObjects : Oui - comptes/groupes privileges, DC et GPO-DC inclus" -ForegroundColor Cyan } if ($UnlimitedSearch.IsPresent) { Write-Host " + UnlimitedSearch : Oui - recherche sans limite" -ForegroundColor Cyan } if ($SinglePageReport.IsPresent) { Write-Host " + SinglePageReport : Oui - rapport en une seule page" -ForegroundColor Cyan } if ($ShowEoLOverview.IsPresent) { Write-Host " + ShowEoLOverview : Oui - apercu EoL affiche" -ForegroundColor Cyan } if (-not $LimitedView -or $ShowSensitiveObjects.IsPresent) { Write-Host " + LimitedView : Non - tous les comptes inclus" -ForegroundColor Yellow } else { Write-Host " + LimitedView : Oui (defaut) - comptes privileges exclus" -ForegroundColor DarkGray } Write-Host " + MaxSearchObjects : $MaxSearchObjects" -ForegroundColor DarkGray Write-Host " + MaxSearchGroups : $MaxSearchGroups" -ForegroundColor DarkGray $_ouDesc = switch ($OUSearchScope) { "Onelevel" { "Niveau direct uniquement (enfants directs)" } "Subtree" { "Arborescence complete (tous les niveaux)" } "Base" { "OU de base uniquement" } default { $OUSearchScope } } Write-Host " + OUSearchScope : $OUSearchScope ($_ouDesc)" -ForegroundColor DarkGray Write-Host " + Seuils inactivite : Admin=$AdminInactivityThreshold j | User=$UserInactivityThreshold j | PC=$ComputerInactivityThreshold j" -ForegroundColor DarkGray Write-Host " + Seuils alertes : DesactivesPct=$DisabledAccountsThreshold% | GroupesVides=$EmptyGroupsThreshold% | PwdNoExpire=$PasswordNeverExpiresThreshold%" -ForegroundColor DarkGray Write-Host " + Objets recents (fenetre) : $RecentObjectsDays jours (utilisateurs + ordinateurs)" -ForegroundColor DarkGray Write-Host "" #region Dashboard . "$PSScriptRoot\MAD-Dashboard.ps1" #endregion Dashboard #region groups . "$PSScriptRoot\MAD-Groups.ps1" #endregion groups #region OU . "$PSScriptRoot\MAD-OU.ps1" #endregion OU #region Users . "$PSScriptRoot\MAD-Users.ps1" #endregion Users #region GPO . "$PSScriptRoot\MAD-GPO.ps1" #endregion GPO #region Trusts . "$PSScriptRoot\MAD-Trusts.ps1" #endregion Trusts #region Printers . "$PSScriptRoot\MAD-Printers.ps1" #endregion Printers #region Computers . "$PSScriptRoot\MAD-Computers.ps1" #endregion Computers #region EoLCalendar . "$PSScriptRoot\MAD-EoL.ps1" #endregion EoLCalendar #Start ConsoleEnd . "$PSScriptRoot\MAD-Console-End.ps1" #endregion ConsoleEnd Write-Progress-Custom "Rapport HTML" "Création du fichier" #region Resume . "$PSScriptRoot\MAD-Resume.ps1" #endregion Resume <########################### Sortie HTML ############################> $OutputPath = $SavePath + '\ADModern.html' . "$PSScriptRoot\MAD-HTML-MultiPage.ps1" . "$PSScriptRoot\MAD-HTML-OnePage.ps1" if ($SinglePageReport.IsPresent ) { HTMLOnePage } else { HTMLMultiPage } # ============================================================================ # RAPPORT TERMINÉ # ============================================================================ Write-Host "" Write-Success "Rapport HTML généré avec succès!" Write-Host "" Write-Info "Fichier généré" $OutputPath "Green" Write-Info "Taille du fichier" "$([math]::Round((Get-Item $OutputPath).Length / 1MB, 2)) MB" "Cyan" Write-Info "Heure de fin" (Get-Date -Format "HH:mm:ss") "White" Write-Host "" Write-Host " ╔═══════════════════════════════════════════════════════════════════════════╗" -ForegroundColor Green Write-Host " ║ ║" -ForegroundColor Green Write-Host " ║" -ForegroundColor Green -NoNewline Write-Host " RAPPORT TERMINE " -ForegroundColor White -NoNewline Write-Host "║" -ForegroundColor Green Write-Host " ║ ║" -ForegroundColor Green Write-Host " ╚═══════════════════════════════════════════════════════════════════════════╝" -ForegroundColor Green Write-Host "" # B04 : ouverture du rapport geree par PSWriteHTML via ShowHTML=$true dans MAD-HTML-*.ps1 # (Start-Process supprime — evite la double ouverture) } #region Update EoL Database function Update-ADEoLDatabase { [CmdletBinding()] param( [Parameter(Mandatory=$false)] [string[]]$Products = @("windows", "windows-server", "ubuntu", "macos", "debian", "rhel", "sles"), [Parameter(Mandatory=$false)] [switch]$Force ) # TOUJOURS recharger EoL-Functions.ps1 pour prendre en compte les modifications $modulePath = $PSScriptRoot if ($modulePath) { $eolPath = Join-Path $modulePath "EoL-Functions.ps1" if (Test-Path $eolPath) { try { # Forcer le rechargement à chaque appel . $eolPath Write-Verbose "EoL-Functions.ps1 rechargé depuis: $eolPath" } catch { Write-Host "" Write-Host "[ERROR] Impossible de charger EoL-Functions.ps1: $($_.Exception.Message)" -ForegroundColor Red Write-Host "" return } } else { Write-Host "" Write-Host "[ERROR] Fichier EoL-Functions.ps1 introuvable dans: $modulePath" -ForegroundColor Red Write-Host "" return } } # Appeler la fonction originale — elle gère elle-même l'affichage complet (header + footer) Update-EoLFromAPI -Products $Products -Force:$Force -FamilyMap $script:OSFamilyMap } Set-Alias -Name "Update-EoL" -Value "Update-ADEoLDatabase" -ErrorAction SilentlyContinue #endregion Update EoL Database Export-ModuleMember -Function Get-MADReport, Update-ADEoLDatabase -Alias Update-EoL |