.temp_commit_revert/UserAdminModule-6383df066ad425f1fcb580c09aa46e3edd8eeea2/Public/Invoke-PersonalModulesMenu.ps1
|
#requires -Version 5.1 function Invoke-PersonalModulesMenu { <# .SYNOPSIS Interactive menu to import PowerShell submodule categories using PSMenu. .DESCRIPTION Displays an interactive multi-select menu of all discovered submodule categories — both built-in (Shell, ADFunctions, etc.) and any user-created custom categories. Categories are discovered dynamically at runtime; no reconfiguration is needed when new submodules are added under the configured custom modules path. Use arrow keys to navigate, Space to select/deselect, and Enter to confirm. Requires the PSMenu module. If PSMenu is not installed the function exits with a clear warning and the install command. Reference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module .PARAMETER ShowDescriptions If specified, appends a short description to each category name in the menu. .EXAMPLE Invoke-PersonalModulesMenu Shows the interactive menu with category names only. .EXAMPLE Invoke-PersonalModulesMenu -ShowDescriptions Shows the menu with descriptions appended to each category name. .NOTES Author: Luke Leigh Requires: PSMenu (Install-Module PSMenu) Tested on: PowerShell 5.1 and 7+ Reference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module .LINK Import-PersonalModules Initialize-UserAdminModule New-PSM1Module #> [CmdletBinding()] param( [Parameter()] [switch]$ShowDescriptions ) trap { Write-Error "Invoke-PersonalModulesMenu failed: $_"; break } # PSMenu is a soft dependency — warn gracefully rather than breaking on load if (-not (Get-Module -ListAvailable -Name PSMenu)) { Write-Warning 'PSMenu module is required for the interactive menu. Install it with: Install-Module PSMenu' return } Import-Module PSMenu -Force -ErrorAction SilentlyContinue # Known descriptions for built-in categories (user categories get a generic label) $knownDescriptions = @{ 'ADFunctions' = 'Active Directory — user lifecycle, groups, auditing, diagnostics.' 'Azure' = 'Azure and Entra ID — resource provisioning, identity governance.' 'CertificateUtilities' = 'PKI utilities — certificate operations, validation, enrollment.' 'CiscoSecure' = 'VPN and Cisco Secure endpoint management.' 'CustomRDGCommands' = 'Custom RDG-specific computer and group management commands.' 'Database' = 'SQL Server operations — queries, backups, configuration.' 'EnvironmentManagement' = 'Environment variables, path operations, system configuration.' 'Exchange' = 'Exchange and M365 — mailboxes, calendars, distribution lists.' 'FileOperations' = 'File and directory manipulation, copying, moving.' 'JekyllBlog' = 'Jekyll static site generation and blog management.' 'Logging' = 'Event logging, audit trails, monitoring.' 'MediaManagement' = 'Audio and video file processing and format conversion.' 'Network' = 'IP, DNS, connectivity testing, network configuration.' 'PKICertificateTools' = 'Advanced PKI — ADCS integration, certificate lifecycle.' 'PrintManagement' = 'Print spooler and printer queue management.' 'ProcessServiceSchedules' = 'Windows services, scheduled tasks, startup configuration.' 'RDGAdmin' = 'RDG admin orchestration — Exchange Online, Azure, Teams, Intune.' 'Registry' = 'Windows registry access and key management.' 'RemoteConnections' = 'RDP, PSRemoting, distributed system connectivity.' 'Replication' = 'Active Directory replication monitoring and diagnostics.' 'Reporting' = 'Reporting and audit exports — CSV, HTML, JSON outputs.' 'Security' = 'Security configuration, compliance, access control.' 'Shell' = 'PowerShell environment utilities, module management, profile helpers.' 'ShutdownCommands' = 'System shutdown, restart, and power management.' 'Teams' = 'Microsoft Teams management and integration.' 'Testing' = 'Test utilities, validation functions, diagnostic tools.' 'TimeTools' = 'Time synchronisation, NTP, time zone management.' 'Utilities' = 'General-purpose utility functions.' 'Virtualization' = 'Hyper-V and virtual machine management.' 'Weather' = 'Weather data retrieval utilities.' } # --- Discover categories dynamically --- $discovered = [System.Collections.Generic.List[string]]::new() # Built-in submodules (discovered from module root) # Use $script:UAMModuleRoot rather than $PSScriptRoot; this file is in Public/ so # $PSScriptRoot would point to Public/, not the module root where submodules live. $_uamRoot = if ($Script:UAMModuleRoot) { $Script:UAMModuleRoot } else { Split-Path $PSScriptRoot -Parent } if (Test-Path $_uamRoot) { Get-ChildItem -Path $_uamRoot -Directory -ErrorAction SilentlyContinue | Where-Object { Test-Path (Join-Path $_.FullName "$($_.Name).psm1") } | ForEach-Object { $discovered.Add($_.Name) } } # Custom submodules from config $cfg = if (Get-Command Get-UserAdminModuleConfig -ErrorAction SilentlyContinue) { Get-UserAdminModuleConfig -ErrorAction SilentlyContinue } if ($cfg -and $cfg.CustomModulesPath -and (Test-Path $cfg.CustomModulesPath)) { Get-ChildItem -Path $cfg.CustomModulesPath -Directory -ErrorAction SilentlyContinue | Where-Object { Test-Path (Join-Path $_.FullName "$($_.Name).psm1") } | ForEach-Object { if (-not $discovered.Contains($_.Name)) { $discovered.Add($_.Name) } } } $categories = $discovered | Sort-Object if ($categories.Count -eq 0) { Write-Warning 'No submodule categories were discovered. Run Initialize-UserAdminModule to configure a custom modules path, then use New-PSM1Module to scaffold your first submodule.' return } $menuItems = if ($ShowDescriptions) { $categories | ForEach-Object { $desc = if ($knownDescriptions.ContainsKey($_)) { $knownDescriptions[$_] } else { 'Custom submodule' } "$_ — $desc" } } else { $categories } Write-Host '' Write-Host ' UserAdminModule — Category Import Menu' -ForegroundColor Cyan Write-Host ' Space to select/deselect | Enter to confirm | Ctrl+C to cancel' -ForegroundColor DarkGray Write-Host '' [int[]]$selectedIndexes = Show-Menu -MenuItems $menuItems -MultiSelect -ReturnIndex -ItemFocusColor 'Cyan' if ($null -eq $selectedIndexes -or $selectedIndexes.Count -eq 0) { Write-Host ' No categories selected.' -ForegroundColor Yellow return } [string[]]$selectedCats = $selectedIndexes | ForEach-Object { $categories[$_] } Write-Host '' Write-Host ' Selected:' -ForegroundColor Green $selectedCats | ForEach-Object { Write-Host " + $_" -ForegroundColor Green } Write-Host '' $confirm = Read-Host ' Proceed with import? [Y/n]' if ($confirm -eq '' -or $confirm -like 'y*') { Write-Host '' Import-PersonalModules -Category $selectedCats Write-Host ' Import complete.' -ForegroundColor Green Write-Host '' } else { Write-Host ' Cancelled.' -ForegroundColor Yellow } Write-Verbose 'Invoke-PersonalModulesMenu completed.' } |