Public/Get-PathAnalysis.ps1
|
function Get-PathAnalysis { <# .SYNOPSIS Analyzes the Windows PATH environment variable for issues. .DESCRIPTION Scans both User and Machine PATH entries to detect: - Paths that no longer exist (obsolete) - Duplicate entries - Invalid paths .PARAMETER Target Which PATH to analyze: User, Machine, or Both. Default is Both. .PARAMETER IssuesOnly If specified, only returns entries with issues. .EXAMPLE Get-PathAnalysis .EXAMPLE Get-PathAnalysis -Target User -IssuesOnly #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [ValidateSet('User', 'Machine', 'Both')] [string]$Target = 'Both', [switch]$IssuesOnly ) $results = @() $entries = Get-PathEntries -Target Both # Always get both for cross-scope detection $allPaths = @() # Find cross-scope duplicates (User paths that exist in Machine) $crossScopeDuplicates = Find-CrossScopeDuplicates -UserPaths $entries.User -MachinePaths $entries.Machine $crossScopeUserPaths = @{} foreach ($dup in $crossScopeDuplicates) { $normalized = $dup.ExpandedPath $crossScopeUserPaths[$normalized] = $dup.MachinePath } # Process User paths (only if requested) if ($Target -eq 'User' -or $Target -eq 'Both') { foreach ($path in $entries.User) { $allPaths += @{ Path = $path Scope = 'User' } } } # Process Machine paths (only if requested) if ($Target -eq 'Machine' -or $Target -eq 'Both') { foreach ($path in $entries.Machine) { $allPaths += @{ Path = $path Scope = 'Machine' } } } # Track seen paths for duplicate detection $seenPaths = @{} foreach ($item in $allPaths) { $testResult = Test-PathEntry -Path $item.Path $normalizedPath = $testResult.Expanded.TrimEnd('\').ToLowerInvariant() # Determine issues $issues = @() $status = '✓' if (-not $testResult.Exists) { $issues += 'Does not exist' $status = '✗' } if ($seenPaths.ContainsKey($normalizedPath)) { $issues += "Duplicate of: $($seenPaths[$normalizedPath])" $status = '⚠' } else { $seenPaths[$normalizedPath] = $item.Path } # Check for cross-scope redundancy (User paths that exist in Machine) if ($item.Scope -eq 'User' -and $crossScopeUserPaths.ContainsKey($normalizedPath)) { $issues += "Redundant (exists in Machine PATH)" if ($status -eq '✓') { $status = '⚠' } } $resultItem = [PSCustomObject]@{ Status = $status Path = $item.Path Scope = $item.Scope Exists = $testResult.Exists Issue = if ($issues.Count -gt 0) { $issues -join '; ' } else { '-' } ExpandedPath = $testResult.Expanded } if ($IssuesOnly) { if ($issues.Count -gt 0) { $results += $resultItem } } else { $results += $resultItem } } # Add summary info $userCharCount = Get-PathCharacterCount -Paths $entries.User $machineCharCount = Get-PathCharacterCount -Paths $entries.Machine $crossScopeCount = $crossScopeDuplicates.Count Write-Verbose "User PATH: $($entries.User.Count) entries, $userCharCount characters" Write-Verbose "Machine PATH: $($entries.Machine.Count) entries, $machineCharCount characters" Write-Verbose "Cross-scope redundant entries: $crossScopeCount" Write-Verbose "Total issues found: $(($results | Where-Object { $_.Status -ne '✓' }).Count)" return $results } |