Public/Optimize-PathOrder.ps1
|
function Optimize-PathOrder { <# .SYNOPSIS Analyzes and optionally applies an optimized PATH order. .DESCRIPTION Sorts PATH entries by priority category to ensure critical system paths come first, followed by development tools, language runtimes, etc. Priority order: 1. System Critical (Windows\System32, wbem, OpenSSH) 2. Windows Core 3. PowerShell 7 4. Development Tools (Git, VS Code, dotnet) 5. Language Runtimes (Python, Node, Go, Java) 6. Package Managers (chocolatey, npm) 7. SDK/Cloud Tools (Docker, Azure, AWS) 8. Security Tools (GPG, SSH, PuTTY) 9. Applications (Program Files) 10. User Applications (AppData) 11. Other .PARAMETER Target Which PATH to optimize: User or Machine. Default is User. .PARAMETER WhatIf Shows what changes would be made without applying them. .PARAMETER Force Skips confirmation prompt. .EXAMPLE Optimize-PathOrder -Target User -WhatIf .EXAMPLE Optimize-PathOrder -Target User #> [CmdletBinding(SupportsShouldProcess)] param( [ValidateSet('User', 'Machine')] [string]$Target = 'User', [switch]$Force ) # Check for admin rights if targeting Machine if ($Target -eq 'Machine') { $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Write-Error "Administrator privileges required to modify the Machine PATH. Please run PowerShell as Administrator." return } } # Get current PATH $currentPath = [Environment]::GetEnvironmentVariable('PATH', $Target) $currentPaths = $currentPath -split ';' | Where-Object { $_ -ne '' } # Get optimized order with categories $categorized = Get-OptimizedPathOrder -Paths $currentPaths -ShowCategories $optimizedPaths = $categorized | Select-Object -ExpandProperty Path # Calculate changes $changes = Compare-PathOrder -CurrentPaths $currentPaths -OptimizedPaths $optimizedPaths # Display analysis Write-Host Write-Host " PATH Order Optimization for [$Target]" -ForegroundColor Cyan Write-Host " ═══════════════════════════════════════════════════════════" -ForegroundColor DarkGray Write-Host # Show categories summary Write-Host " 📊 Category Distribution:" -ForegroundColor Yellow $categoryGroups = $categorized | Group-Object Category | Sort-Object { $_.Group[0].Priority } foreach ($group in $categoryGroups) { $priority = $group.Group[0].Priority $icon = switch -Wildcard ($group.Name) { 'System*' { '🔒' } 'Windows*' { '🪟' } 'PowerShell*' { '⚡' } 'Development*' { '🛠️' } 'Language*' { '🐍' } 'Package*' { '📦' } 'SDK*' { '☁️' } 'Security*' { '🔐' } 'Application*' { '📁' } default { '📄' } } Write-Host " $icon $($group.Name): $($group.Count) entries" -ForegroundColor White } Write-Host # Show proposed order Write-Host " 📋 Proposed Order:" -ForegroundColor Yellow Write-Host " ─────────────────────────────────────────────────────────" -ForegroundColor DarkGray $position = 1 $lastCategory = '' foreach ($entry in $categorized) { if ($entry.Category -ne $lastCategory) { if ($lastCategory -ne '') { Write-Host } Write-Host " ── $($entry.Category) ──" -ForegroundColor DarkCyan $lastCategory = $entry.Category } $truncatedPath = if ($entry.Path.Length -gt 55) { $entry.Path.Substring(0, 52) + '...' } else { $entry.Path } $moved = $entry.OriginalPosition -ne ($position - 1) $color = if ($moved) { 'Yellow' } else { 'Gray' } $indicator = if ($moved) { '→' } else { ' ' } Write-Host " $indicator $position. $truncatedPath" -ForegroundColor $color $position++ } Write-Host Write-Host " ─────────────────────────────────────────────────────────" -ForegroundColor DarkGray Write-Host # Summary $movedCount = ($changes | Measure-Object).Count if ($movedCount -eq 0) { Write-Host " ✓ PATH is already in optimal order!" -ForegroundColor Green return [PSCustomObject]@{ Success = $true ChangesNeeded = $false Message = 'PATH is already optimized' } } Write-Host " Changes needed: $movedCount entries will be reordered" -ForegroundColor Yellow Write-Host # WhatIf handling if ($WhatIfPreference) { Write-Host " [WhatIf] Would apply the optimized PATH order to $Target scope." -ForegroundColor Magenta return [PSCustomObject]@{ Success = $true ChangesNeeded = $true WhatIf = $true EntriesReordered = $movedCount } } # Confirmation if (-not $Force) { Write-Host " ⚠️ WARNING: Reordering PATH can affect which programs run by default." -ForegroundColor Yellow Write-Host " A backup will be created before making changes." -ForegroundColor DarkGray Write-Host $confirm = Read-Host " Apply optimized order? (Y/N)" if ($confirm -ne 'Y' -and $confirm -ne 'y') { Write-Host " Operation cancelled." -ForegroundColor Gray return [PSCustomObject]@{ Success = $false Cancelled = $true } } } # Create backup $backup = Backup-Path -Target $Target Write-Host " ✓ Backup created: $($backup.BackupFile)" -ForegroundColor Green # Build and apply new PATH $newPath = $optimizedPaths -join ';' try { [Environment]::SetEnvironmentVariable('PATH', $newPath, $Target) Write-Host Write-Host " ✓ PATH order optimized successfully!" -ForegroundColor Green Write-Host " Note: You may need to restart your terminal for changes to take effect." -ForegroundColor DarkGray return [PSCustomObject]@{ Success = $true Target = $Target EntriesReordered = $movedCount BackupFile = $backup.BackupFile } } catch { Write-Error "Failed to update PATH: $_" return [PSCustomObject]@{ Success = $false Error = $_.Exception.Message } } } |