Private/Import-NSPToolkitModule.ps1
|
# Shared sibling-module loader. CANONICAL COPY: NSP-Toolkit\Private\Import-NSPToolkitModule.ps1. # NSP.ActiveDirectory / NSP.NPS / NSP.PKI / NSP.FortiClient carry generated copies - edit this file, # then run NSP-Toolkit\tools\Sync-SharedLoader.ps1. Each repo's tests fail when its copy drifts. function Import-NSPToolkitModule { <# .SYNOPSIS Loads a sibling NSP toolkit module on first use: an installed copy, else a checkout next to this repository (NSP-PoSHToolkits\NSP-X or GitRepo\NSP-X), else installs it from the PowerShell Gallery. .DESCRIPTION These modules are never RequiredModules entries, so each module still imports on a bare host. With -MinimumVersion, an older installed copy is passed over and a loaded older copy replaced. The Gallery install is what lets a plain `Install-Module NSP.<Tool>` work on its own: the siblings arrive the first time they're needed. It is announced before it happens (module, version, scope - AllUsers when elevated, else CurrentUser) and reported after. NSP_NO_AUTOINSTALL=1 turns it off and fails with the Install-Module command to run instead; the test runners set it so a test never reaches the network. The import is -Global on purpose: NSP.Toolkit holds session-wide state (the dry-run switch, work-folder paths, tool versions) that every tool module must share, and a module-scoped import per caller could leave two different versions loaded in one session. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Name, [version]$MinimumVersion, [switch]$Reload ) $loaded = Get-Module -Name $Name | Sort-Object Version -Descending | Select-Object -First 1 if ($loaded -and -not $Reload -and (-not $MinimumVersion -or $loaded.Version -ge $MinimumVersion)) { return } $findInstalled = { $m = Get-Module -ListAvailable -Name $Name | Where-Object { -not $MinimumVersion -or $_.Version -ge $MinimumVersion } | Sort-Object Version -Descending | Select-Object -First 1 if ($m) { $m.Path } } $path = & $findInstalled if (-not $path) { $folder = $Name.Replace('.', '-') $toolkits = Split-Path -Parent $script:ModuleRoot foreach ($candidate in @((Join-Path $toolkits "$folder\$Name.psd1"), (Join-Path (Split-Path -Parent $toolkits) "$folder\$Name.psd1"))) { if (-not (Test-Path -LiteralPath $candidate)) { continue } if ($MinimumVersion -and [version](Import-PowerShellDataFile -LiteralPath $candidate).ModuleVersion -lt $MinimumVersion) { continue } $path = $candidate break } } $wanted = if ($MinimumVersion) { "$Name $MinimumVersion or later" } else { $Name } $installError = $null if (-not $path -and $env:NSP_NO_AUTOINSTALL -ne '1') { try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 $identity = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() $scope = if ($identity.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { 'AllUsers' } else { 'CurrentUser' } Write-Host "$wanted is needed and not installed - installing it from the PowerShell Gallery (scope $scope)..." -ForegroundColor Cyan if (-not (Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction SilentlyContinue | Where-Object { $_.Version -ge [version]'2.8.5.201' })) { Write-Host " Installing the NuGet package provider first (scope $scope)." -ForegroundColor DarkGray Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope $scope -ErrorAction Stop | Out-Null } $install = @{ Name = $Name; Repository = 'PSGallery'; Scope = $scope; Force = $true; AllowClobber = $true; ErrorAction = 'Stop' } if ($MinimumVersion) { $install.MinimumVersion = $MinimumVersion } Install-Module @install $path = & $findInstalled if ($path) { $got = (Import-PowerShellDataFile -LiteralPath $path).ModuleVersion Write-Host " Installed $Name $got ($scope)." -ForegroundColor DarkGray } } catch { $installError = $_.Exception.Message } } if (-not $path) { $why = if ($installError) { " Installing it from the PowerShell Gallery failed: $installError" } else { '' } throw "$wanted is required for this operation.$why Install it (Install-Module $Name), or check out $($Name.Replace('.', '-')) next to this repository." } if ($loaded) { Remove-Module -Name $Name -Force } Import-Module $path -Global -ErrorAction Stop } |