Public/Initialize-UserAdminModule.ps1
|
#requires -Version 5.1 function Initialize-UserAdminModule { <# .SYNOPSIS One-time setup that configures UserAdminModule for a new administrator. .DESCRIPTION Sets up the UserAdminModule framework for first use by: - Storing the custom submodules path in $env:APPDATA\UserAdminModule\config.json - Creating the custom path directory if it does not already exist - Optionally writing 'Import-Module UserAdminModule' to $PROFILE Once configured, Import-PersonalModules and Invoke-PersonalModulesMenu will automatically discover any submodules you create under the configured path. Use New-PSM1Module to scaffold your first submodule. Reference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module .PARAMETER Path The folder where your custom submodule folders will be stored. Example: C:\MyModules .PARAMETER UpdateProfile If specified, appends 'Import-Module UserAdminModule' to the current user's PowerShell profile ($PROFILE). A .bak backup of the existing profile is created before any change is made. .PARAMETER UseSharedProfile When combined with -UpdateProfile, writes a dot-source line for the bundled SharedPowershellProfile.ps1 (PS 7+) or SharedWindowsPowershellProfile.ps1 (PS 5.1) instead of a plain Import-Module line. The correct file is chosen automatically based on $PSEdition. The shared profile configures the full shell UX: admin prompt, console sizing, PSReadLine prediction, greeting, and startup timer. .EXAMPLE Initialize-UserAdminModule -Path 'C:\MyModules' Configures the custom modules path. Submodules created here are auto-discovered by Import-PersonalModules and Invoke-PersonalModulesMenu. .EXAMPLE Initialize-UserAdminModule -Path 'C:\MyModules' -UpdateProfile Configures the custom path and adds the Import-Module line to $PROFILE so UserAdminModule loads automatically in every new session. .EXAMPLE Initialize-UserAdminModule -Path 'C:\MyModules' -UpdateProfile -UseSharedProfile Configures the custom path and writes the full shared profile dot-source line to $PROFILE. On PS 7+ this loads SharedPowershellProfile.ps1; on PS 5.1 it loads SharedWindowsPowershellProfile.ps1. Both configure the admin prompt, console sizing, PSReadLine prediction, greeting, and startup timer. .EXAMPLE Initialize-UserAdminModule -Path 'C:\MyModules' -WhatIf Shows what would happen without making any changes. .OUTPUTS System.Management.Automation.PSCustomObject Properties: CustomModulesPath, ConfigPath, ProfileUpdated .NOTES Author: Luke Leigh Config: $env:APPDATA\UserAdminModule\config.json Tested on: PowerShell 5.1 and 7+ Reference: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module .LINK Get-UserAdminModuleConfig Import-PersonalModules New-PSM1Module Invoke-PersonalModulesMenu #> [CmdletBinding(SupportsShouldProcess)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position = 0, HelpMessage = 'Path to store your custom submodule folders.')] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter()] [switch]$UpdateProfile, [Parameter()] [switch]$UseSharedProfile ) begin { trap { Write-Error "Failed to initialise UserAdminModule: $_" break } $configDir = Join-Path $env:APPDATA 'UserAdminModule' $configPath = Join-Path $configDir 'config.json' } process { trap { Write-Error "Failed during UserAdminModule initialisation: $_" continue } # 1 — Resolve and create the custom modules directory $resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) if (-not (Test-Path $resolvedPath)) { if ($PSCmdlet.ShouldProcess($resolvedPath, 'Create custom modules directory')) { New-Item -Path $resolvedPath -ItemType Directory -Force | Out-Null Write-Verbose "Created custom modules directory: $($resolvedPath)" } } else { Write-Verbose "Custom modules directory already exists: $($resolvedPath)" } # 2 — Create config directory and write config if (-not (Test-Path $configDir)) { New-Item -Path $configDir -ItemType Directory -Force | Out-Null } $config = [PSCustomObject]@{ CustomModulesPath = $resolvedPath ConfigVersion = '1.0' } if ($PSCmdlet.ShouldProcess($configPath, 'Write UserAdminModule config')) { $config | ConvertTo-Json | Set-Content -Path $configPath -Encoding UTF8 -Force Write-Verbose "Config written to: $($configPath)" } # 3 — Optionally update $PROFILE $profileUpdated = $false if ($UpdateProfile) { $profilePath = $PROFILE # Build the profile line to write if ($UseSharedProfile) { # Pick the correct shared profile based on PS edition. # PS 5.1 = Desktop edition; PS 7+ = Core edition. $_sharedFile = if ($PSEdition -eq 'Desktop') { 'SharedWindowsPowershellProfile.ps1' } else { 'SharedPowershellProfile.ps1' } # Resolve the bundled profile path from the installed module. $_uamBase = (Get-Module UserAdminModule -ErrorAction SilentlyContinue).ModuleBase if (-not $_uamBase) { $_uamBase = if ($Script:UAMModuleRoot) { $Script:UAMModuleRoot } else { Split-Path $PSScriptRoot -Parent } } $_sharedPath = Join-Path $_uamBase "profiles\$($_sharedFile)" $importLine = ". `"$($_sharedPath)`"" $_matchPattern = 'SharedPowershellProfile|SharedWindowsPowershellProfile' } else { $importLine = 'Import-Module UserAdminModule -ErrorAction SilentlyContinue' $_matchPattern = 'Import-Module UserAdminModule' } if (-not (Test-Path $profilePath)) { if ($PSCmdlet.ShouldProcess($profilePath, 'Create PowerShell profile file')) { New-Item -Path $profilePath -ItemType File -Force | Out-Null } } $existingContent = Get-Content -Path $profilePath -Raw -ErrorAction SilentlyContinue if ($existingContent -notmatch $_matchPattern) { if ($PSCmdlet.ShouldProcess($profilePath, "Add profile line to $($profilePath)")) { $backupPath = "$profilePath.bak" if (Test-Path $profilePath) { Copy-Item -Path $profilePath -Destination $backupPath -Force Write-Verbose "Profile backup created at: $($backupPath)" } Add-Content -Path $profilePath -Value "`n$importLine" -Encoding UTF8 Write-Verbose "Added profile line to: $($profilePath)" $profileUpdated = $true } } else { Write-Verbose 'Profile already contains a UserAdminModule entry — no change made.' $profileUpdated = $true } } # 4 — Return result object [PSCustomObject]@{ CustomModulesPath = $resolvedPath ConfigPath = $configPath ProfileUpdated = $profileUpdated } } end { trap { Write-Error "Failed in Initialize-UserAdminModule end block: $_" continue } Write-Information "UserAdminModule configured. Custom modules path: $($resolvedPath)" -InformationAction Continue Write-Information "Next: use New-PSM1Module -folderPath '$($resolvedPath)\MyCategory' to scaffold your first submodule." -InformationAction Continue if ($UpdateProfile -and -not $UseSharedProfile) { Write-Information 'Tip: re-run with -UseSharedProfile to configure the full shell UX (admin prompt, greeting, PSReadLine prediction). Example: Initialize-UserAdminModule -Path <path> -UpdateProfile -UseSharedProfile' -InformationAction Continue } Write-Verbose 'Initialize-UserAdminModule completed.' } } |