Public/Move-NSPToolLegacyData.ps1
|
function Move-NSPToolLegacyData { <# .SYNOPSIS Finds what the zip-era version of a tool left on this server - extracted tool folders, answers files next to the old scripts, hand-back files, old shims with answers embedded - moves the data into the tool's work folder, then removes the old copies. .DESCRIPTION 1. Finds the old extract folders (e.g. NPSStaging\NPSManager next to an NPS-Manager.ps1 shim) and old shims that still carry an embedded answers block, under -SearchPath. 2. Merges the old answers file into the work folder's answers (the work folder wins; a differing field is prompted for unless -NonInteractive). 3. Copies hand-back files and certificates (*_Response.json, ADInventory_*.json, *.pfx, *.cer) into the work folder's Responses\Legacy - PFX files are kept, they are password-protected. 4. Lists what it will remove and asks once, then deletes the old extract folders and blanks the answers embedded in old shims (the shim file itself stays). 5. Logs what moved and what was removed - names only, never values - to Logs\. -WhatIf lists everything and changes nothing. Returns a summary object. .PARAMETER Tool Tool key: AD, NPS, PKI, FortiClient. .PARAMETER SearchPath Folders to search (two levels deep). Defaults to C:\Admin, C:\Temp, C:\Scripts, C:\NSP and every user's Desktop and Downloads, plus any fixed path the tool used. .PARAMETER NonInteractive Never prompt: the work folder wins differing answers, and removal goes ahead without asking. .EXAMPLE Move-NSPToolLegacyData -Tool NPS -WhatIf .EXAMPLE Move-NSPToolLegacyData -Tool PKI -SearchPath 'D:\Tools' #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]$Tool, [string[]]$SearchPath, [switch]$NonInteractive ) $def = Get-NSPToolDefinition -Tool $Tool $legacy = $def.Legacy if (-not $SearchPath) { $SearchPath = @('C:\Admin', 'C:\Temp', 'C:\Scripts', 'C:\NSP') foreach ($userDir in @(Get-ChildItem -LiteralPath (Join-Path $env:SystemDrive 'Users') -Directory -ErrorAction SilentlyContinue)) { $SearchPath += (Join-Path $userDir.FullName 'Desktop'), (Join-Path $userDir.FullName 'Downloads') } } $roots = @($SearchPath | Where-Object { $_ -and (Test-Path -LiteralPath $_) }) # --- 1. find ----------------------------------------------------------------------------- $extractDirs = @() $removeDirs = @() if ($legacy.StagingFolder) { foreach ($root in $roots) { $found = @(Get-ChildItem -LiteralPath $root -Directory -Recurse -Depth 2 -ErrorAction SilentlyContinue | Where-Object { $_.Name -eq $legacy.StagingFolder }) foreach ($staging in $found) { $removeDirs += $staging.FullName $extract = Join-Path $staging.FullName $legacy.ExtractFolder if (Test-Path -LiteralPath $extract) { $extractDirs += $extract } } } } foreach ($fixed in @($legacy.FixedPaths)) { if ($fixed -and (Test-Path -LiteralPath $fixed)) { $removeDirs += $fixed; $extractDirs += $fixed } } $removeDirs = @($removeDirs | Select-Object -Unique) $extractDirs = @($extractDirs | Select-Object -Unique) $shims = @() if ($legacy.ShimAnswersVar) { $marker = '$' + $legacy.ShimAnswersVar + " = @'" foreach ($root in $roots) { foreach ($name in @($legacy.ShimNames)) { $shims += @(Get-ChildItem -LiteralPath $root -Filter $name -File -Recurse -Depth 2 -ErrorAction SilentlyContinue | Where-Object { (Get-NSPLegacyShimAnswers -Path $_.FullName -Variable $legacy.ShimAnswersVar) } | ForEach-Object { $_.FullName }) } } $shims = @($shims | Select-Object -Unique) Write-Verbose "Shim marker: $marker" } $answersFiles = @() $responseFiles = @() foreach ($dir in $extractDirs) { if ($legacy.AnswersFile) { $a = Join-Path $dir $legacy.AnswersFile if (Test-Path -LiteralPath $a) { $answersFiles += $a } } $responseFiles += @(Get-ChildItem -LiteralPath $dir -File -Recurse -Depth 1 -ErrorAction SilentlyContinue | Where-Object { $_.Name -like '*_*Response.json' -or $_.Name -like 'ADInventory_*.json' -or $_.Extension -in '.pfx', '.cer' } | ForEach-Object { $_.FullName }) } $summary = [pscustomobject]@{ Tool = $def.Name; AnswersMerged = @(); ResponsesCopied = @(); FoldersRemoved = @(); ShimsBlanked = @(); Found = $false } if (-not ($removeDirs.Count + $shims.Count)) { Write-Host "No old $($def.DisplayName) files found on this server." -ForegroundColor DarkGray return $summary } $summary.Found = $true Write-Host '' Write-Host "Old $($def.DisplayName) files found:" -ForegroundColor Cyan foreach ($d in $removeDirs) { Write-Host " folder $d" } foreach ($s in $shims) { Write-Host " shim $s (answers embedded)" } foreach ($a in $answersFiles) { Write-Host " answers $a -> work folder" -ForegroundColor DarkGray } foreach ($r in $responseFiles) { Write-Host " file $r -> work folder Responses\Legacy" -ForegroundColor DarkGray } $log = New-Object Collections.Generic.List[string] # --- 2. answers ------------------------------------------------------------------------- $shimSeeds = @(foreach ($s in $shims) { Get-NSPLegacyShimAnswers -Path $s -Variable $legacy.ShimAnswersVar }) foreach ($source in @($answersFiles + $shims)) { $json = if ($answersFiles -contains $source) { [IO.File]::ReadAllText($source) } else { $shimSeeds[[array]::IndexOf($shims, $source)] } try { $incoming = ConvertFrom-Json -InputObject $json -ErrorAction Stop } catch { Write-Warning "Skipping unreadable answers in ${source}: $($_.Exception.Message)"; continue } if ($PSCmdlet.ShouldProcess((Get-NSPToolWorkPath -Tool $def.Name -Kind Answers), "Merge answers from $source")) { $merge = Merge-NSPHandoffAnswers -Live (Get-NSPToolAnswers -Tool $def.Name) -Incoming $incoming -NonInteractive:$NonInteractive Save-NSPToolAnswers -Tool $def.Name -Answers $merge.Answers $summary.AnswersMerged += $source $log.Add("answers merged from $source ($($merge.Added) added, $($merge.TookIncoming)/$($merge.Differing) differing took incoming)") } } # --- 3. hand-back files and certificates -------------------------------------------------- foreach ($r in $responseFiles) { if ($PSCmdlet.ShouldProcess($r, 'Copy into the work folder (Responses\Legacy)')) { $dest = Join-Path (Get-NSPToolWorkPath -Tool $def.Name -Kind Responses -Create) 'Legacy' if (-not (Test-Path -LiteralPath $dest)) { New-Item -ItemType Directory -Path $dest -Force | Out-Null } $target = Join-Path $dest (Split-Path -Leaf $r) $n = 1 while (Test-Path -LiteralPath $target) { $target = Join-Path $dest ('{0}.{1}{2}' -f [IO.Path]::GetFileNameWithoutExtension($r), $n, [IO.Path]::GetExtension($r)); $n++ } Copy-Item -LiteralPath $r -Destination $target $summary.ResponsesCopied += $target $log.Add("copied $r -> $target") } } # --- 4. remove old copies ---------------------------------------------------------------- if (-not $WhatIfPreference) { $go = $NonInteractive if (-not $go) { $q = "Remove the $($removeDirs.Count) old folder(s) and blank the answers in $($shims.Count) old shim(s)? Their data is now in the work folder." try { $go = (Read-Host "$q [y/N]") -match '^(?i)y(es)?$' } catch { $go = $false } } if (-not $go) { Write-Host 'Left the old files in place.' -ForegroundColor Yellow } else { foreach ($d in $removeDirs) { if ($PSCmdlet.ShouldProcess($d, 'Delete old extracted tool folder')) { try { Remove-Item -LiteralPath $d -Recurse -Force -ErrorAction Stop; $summary.FoldersRemoved += $d; $log.Add("removed folder $d") } catch { Write-Warning "Could not remove ${d}: $($_.Exception.Message)" } } } foreach ($s in $shims) { if ($PSCmdlet.ShouldProcess($s, 'Blank the embedded answers')) { if (Clear-NSPLegacyShimAnswers -Path $s -Variable $legacy.ShimAnswersVar) { $summary.ShimsBlanked += $s; $log.Add("blanked answers in shim $s") } } } } } # --- 5. log ------------------------------------------------------------------------------ if ($log.Count -and -not $WhatIfPreference) { $logDir = Get-NSPToolWorkPath -Tool $def.Name -Kind Logs -Create $logFile = Join-Path $logDir ('LegacyCleanup_{0}.log' -f (Get-Date -Format 'yyyyMMdd_HHmmss')) [IO.File]::WriteAllLines($logFile, [string[]]$log) } return $summary } |