Public/Invoke-WinPathClean.ps1
|
function Invoke-WinPathClean { <# .SYNOPSIS Launches the WinPath-Clean interactive TUI. .DESCRIPTION Opens an interactive terminal interface to analyze, review, and clean the Windows PATH environment variable. .EXAMPLE Invoke-WinPathClean .EXAMPLE wpc .NOTES Alias: wpc, pathclean #> [CmdletBinding()] param() $running = $true while ($running) { Clear-TuiScreen # Get analysis $analysis = Get-PathAnalysis -Target Both $issueCount = ($analysis | Where-Object { $_.Status -ne '✓' }).Count $userEntries = ($analysis | Where-Object { $_.Scope -eq 'User' }).Count $machineEntries = ($analysis | Where-Object { $_.Scope -eq 'Machine' }).Count # Count cross-scope duplicates (User paths that exist in Machine) $crossScopeRedundant = ($analysis | Where-Object { $_.Scope -eq 'User' -and $_.Issue -match 'Redundant \(exists in Machine PATH\)' }).Count # Summary Write-Host " 📊 Quick Summary" -ForegroundColor Yellow Write-Host " ─────────────────────────────────────────────────" -ForegroundColor DarkGray Write-Host " Total entries : " -NoNewline -ForegroundColor White Write-Host "$($analysis.Count)" -ForegroundColor Cyan Write-Host " User entries : " -NoNewline -ForegroundColor White Write-Host "$userEntries" -ForegroundColor Cyan Write-Host " Machine entries : " -NoNewline -ForegroundColor White Write-Host "$machineEntries" -ForegroundColor Cyan Write-Host " Issues found : " -NoNewline -ForegroundColor White if ($issueCount -gt 0) { Write-Host "$issueCount" -ForegroundColor Yellow } else { Write-Host "0 ✓" -ForegroundColor Green } if ($crossScopeRedundant -gt 0) { Write-Host " Redundant in User: " -NoNewline -ForegroundColor White Write-Host "$crossScopeRedundant (exist in Machine PATH)" -ForegroundColor DarkYellow } Write-Host # Display table with issues (limited to first 15) $displayData = $analysis | Select-Object -First 20 Write-Host " 📋 PATH Entries (showing first 20)" -ForegroundColor Yellow Write-Host " ─────────────────────────────────────────────────" -ForegroundColor DarkGray Write-Host # Simple table format Write-Host " Status │ Scope │ Path" -ForegroundColor DarkCyan Write-Host " ───────┼─────────┼──────────────────────────────────────────────────" -ForegroundColor DarkGray foreach ($entry in $displayData) { $statusColor = switch ($entry.Status) { '✓' { 'Green' } '⚠' { 'Yellow' } '✗' { 'Red' } default { 'White' } } $truncatedPath = if ($entry.Path.Length -gt 50) { $entry.Path.Substring(0, 47) + '...' } else { $entry.Path } Write-Host " " -NoNewline Write-Host $entry.Status -ForegroundColor $statusColor -NoNewline Write-Host " │ " -ForegroundColor DarkGray -NoNewline Write-Host $entry.Scope.PadRight(7) -ForegroundColor White -NoNewline Write-Host " │ " -ForegroundColor DarkGray -NoNewline Write-Host $truncatedPath -ForegroundColor White } $remaining = $analysis.Count - 20 if ($remaining -gt 0) { Write-Host " ... and $remaining more entries" -ForegroundColor DarkGray } Write-Host Write-Host " ─────────────────────────────────────────────────" -ForegroundColor DarkGray Write-Host # Menu Write-Host " Actions:" -ForegroundColor Cyan Write-Host " [A] Analyze in detail [U] Optimize User PATH [S] Optimize System PATH" -ForegroundColor White Write-Host " [N] Add new path [B] Create backup [R] Restore backup" -ForegroundColor White Write-Host " [E] Export report [Q] Quit" -ForegroundColor White Write-Host Write-Host " (Optimize = removes duplicates/obsolete + reorders by priority)" -ForegroundColor DarkGray Write-Host Write-Host " Select option: " -ForegroundColor Gray -NoNewline $choice = Read-Host switch ($choice.ToUpper()) { 'A' { # Detailed analysis Clear-TuiScreen Write-Host " 📋 Detailed PATH Analysis" -ForegroundColor Yellow Write-Host $analysis | Format-Table -Property Status, Scope, Path, Issue -AutoSize -Wrap Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'U' { # Full optimization of User PATH (clean + reorder) Clear-TuiScreen # Check if there are cross-scope duplicates $removeCrossScope = $false if ($crossScopeRedundant -gt 0) { Write-Host " ⚠ Found $crossScopeRedundant User PATH entries that already exist in Machine PATH" -ForegroundColor Yellow Write-Host " These entries are redundant because Machine PATH is always loaded first." -ForegroundColor DarkGray Write-Host Write-Host " Remove these redundant entries? [Y/N]: " -NoNewline -ForegroundColor White $removeChoice = Read-Host if ($removeChoice -eq 'Y' -or $removeChoice -eq 'y') { $removeCrossScope = $true } Write-Host } if ($removeCrossScope) { Set-CleanPath -Target User -OptimizeOrder -RemoveCrossScopeDuplicates } else { Set-CleanPath -Target User -OptimizeOrder } Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'S' { # Full optimization of System (Machine) PATH (clean + reorder) Clear-TuiScreen if (-not (Test-IsAdmin)) { Write-Host Write-Host " ╔═════════════════════════════════════════════════════════════╗" -ForegroundColor Red Write-Host " ║ ⚠ Administrator privileges required ║" -ForegroundColor Red Write-Host " ╠═════════════════════════════════════════════════════════════╣" -ForegroundColor Red Write-Host " ║ To modify the System PATH, please run PowerShell as Admin ║" -ForegroundColor Yellow Write-Host " ║ Right-click PowerShell → 'Run as Administrator' ║" -ForegroundColor Yellow Write-Host " ╚═════════════════════════════════════════════════════════════╝" -ForegroundColor Red Write-Host } else { Set-CleanPath -Target Machine -OptimizeOrder } Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'N' { # Add new path Clear-TuiScreen Write-Host " ➕ Add New Path" -ForegroundColor Yellow Write-Host Write-Host " Enter path to add (or leave empty to cancel):" -ForegroundColor White Write-Host " > " -NoNewline -ForegroundColor Gray $newPath = Read-Host if ($newPath -and $newPath.Trim() -ne '') { Write-Host Write-Host " Target: [U]ser or [S]ystem? " -NoNewline -ForegroundColor White $targetChoice = Read-Host $pathTarget = if ($targetChoice -eq 'S' -or $targetChoice -eq 's') { 'Machine' } else { 'User' } # Check admin for Machine target if ($pathTarget -eq 'Machine') { if (-not (Test-IsAdmin)) { Write-Host Write-Host " ⚠ Administrator privileges required for System PATH" -ForegroundColor Red Write-Host " Run PowerShell as Administrator to modify System PATH" -ForegroundColor Yellow } else { Add-SafePath -Path $newPath.Trim() -Target $pathTarget } } else { Add-SafePath -Path $newPath.Trim() -Target $pathTarget } } Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'B' { # Create backup Clear-TuiScreen $result = Backup-Path -Target Both Write-Host Write-Host " ✓ Backup created: $($result.BackupFile)" -ForegroundColor Green Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'R' { # Restore from backup Clear-TuiScreen Write-Host " 📂 Available Backups" -ForegroundColor Yellow Write-Host $backups = Get-PathBackups if ($backups.Count -eq 0) { Write-Host " No backups found." -ForegroundColor DarkGray } else { for ($i = 0; $i -lt $backups.Count; $i++) { Write-Host " [$($i + 1)] $($backups[$i].FileName) - $($backups[$i].Created)" -ForegroundColor White } Write-Host Write-Host " Select backup number (or Enter to cancel): " -ForegroundColor Gray -NoNewline $backupChoice = Read-Host if ($backupChoice -match '^\d+$') { $index = [int]$backupChoice - 1 if ($index -ge 0 -and $index -lt $backups.Count) { Restore-Path -BackupFile $backups[$index].FullName } } } Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'E' { # Export report Clear-TuiScreen $reportPath = Join-Path (Get-Location) "path-report_$(Get-Date -Format 'yyyy-MM-dd').json" Export-PathReport -Path $reportPath Write-Host Write-Host "Press Enter to continue..." -ForegroundColor DarkGray Read-Host | Out-Null } 'Q' { $running = $false Clear-Host Write-Host " Thank you for using WinPath-Clean! 🧹" -ForegroundColor Cyan Write-Host } } } } |