@@ -15,111 +15,114 @@ with the newest version ahead of the others.
15
15
16
16
function Initialize-PathCollection
17
17
{
18
- # initialize collections
19
- $Script :app , $Script :user = @ {}, @ ()
20
- # get command extensions
21
- $Script :pathext = $env: PATHEXT -split ' ;'
22
- # get list of directory environment variables
23
- $Script :evmatch = Get-ChildItem env: |
24
- Where-Object {Test-Path $_.Value - PathType Container} |
25
- Where-Object {' windir' , ' TMP' , ' ProgramW6432' , ' CommonProgramW6432' , ' SystemDrive' , ' HomeDrive' , ' HomePath' -inotcontains $_.Name } |
26
- ForEach-Object {$_.Value = ' ^' + ($_.Value.Trim (' \' ) -replace ' (\W)' , ' \$1' ) + ' (?=\\|$)' ; $_ } |
27
- Sort-Object @ {e = {$_.Value.Length };asc = $false }, @ {e = {$_.Name.Length };asc = $true }
18
+ # initialize collections
19
+ $Script :app , $Script :user = @ {}, @ ()
20
+ # get command extensions
21
+ $Script :pathext = $env: PATHEXT -split ' ;'
22
+ # get list of directory environment variables
23
+ $Script :evmatch = Get-ChildItem env: |
24
+ Where-Object {Test-Path $_.Value - PathType Container} |
25
+ Where-Object {' windir' , ' TMP' , ' ProgramW6432' , ' CommonProgramW6432' , ' SystemDrive' , ' HomeDrive' , ' HomePath' -inotcontains $_.Name } |
26
+ ForEach-Object {$_.Value = ' ^' + ($_.Value.Trim (' \' ) -replace ' (\W)' , ' \$1' ) + ' (?=\\|$)' ; $_ } |
27
+ Sort-Object @ {e = {$_.Value.Length };asc = $false }, @ {e = {$_.Name.Length };asc = $true }
28
28
}
29
29
30
30
function Backup-Path ([Parameter (Position = 0 , Mandatory = $true )][EnvironmentVariableTarget ]$Target )
31
31
{
32
- mkdir $env: LOCALAPPDATA \OptimizePath | Out-Null
33
- " $ ( Get-Date - Format u) `t $ ( $Target ) `t $ ( [Environment ]::GetEnvironmentVariable(' Path' , $Target )) " |
34
- Add-Content - Path $env: LOCALAPPDATA \OptimizePath\Backup.tsv
32
+ mkdir $env: LOCALAPPDATA \OptimizePath | Out-Null
33
+ " $ ( Get-Date - Format u) `t $ ( $Target ) `t $ ( [Environment ]::GetEnvironmentVariable(' Path' , $Target )) " |
34
+ Add-Content - Path $env: LOCALAPPDATA \OptimizePath\Backup.tsv
35
35
}
36
36
37
37
filter Get-PathDetail ([Parameter (Position = 0 , Mandatory = $true )][EnvironmentVariableTarget ]$Target ,
38
- [Parameter (Position = 1 , ValueFromPipeline = $true )][string ]$Entry )
38
+ [Parameter (Position = 1 , ValueFromPipeline = $true )][string ]$Entry )
39
39
{
40
- if ([string ]::IsNullOrWhiteSpace($Entry )) {return }
41
- $fullpath = [Environment ]::ExpandEnvironmentVariables($Entry )
42
- Write-Verbose " $Target Path: $Entry $ ( if ($Entry -ne $fullpath ){' (' + $fullpath + ' )' }) "
43
- if (! (Test-Path $fullpath - PathType Container)) {Write-Warning " $Target Path: Entry $Entry not found!" ; return }
44
- if ($Target -ne ' User' -and $entry.StartsWith (" $env: USERPROFILE \" )) {Write-Warning " $Target Path: Entry $entry under user profile!" ; $user += $entry ; continue }
45
- [IO.FileInfo []]$cmd = Get-ChildItem $fullpath - File | Where-Object {$pathext -icontains $_.Extension }
46
- if (! $cmd ) {Write-Warning " $Target Path: Entry $Entry contains no executables." ; return }
47
- elseif ($cmd.Count -eq 1 ) {Write-Warning " $Target Path: Entry $Entry contains only one command! ($ ( $cmd [0 ].Name) )" }
48
- else {Write-Verbose " $Target Path: Entry $Entry contains $ ( $cmd.Count ) commands." }
49
- foreach ($c in $cmd )
50
- {
51
- if ($app [$c.Name ]) {$app [$c.Name ]+= $Entry }
52
- else {[string []]$app [$c.Name ] = $Entry }
53
- }
54
- $ev = $evmatch | Where-Object {$Entry -match $_.Value } | Select-Object - First 1
55
- if ($ev ) {Write-Verbose " $Target Path: $entry matches $ ( $ev.Name ) /$ ( $ev.Value ) /" }
56
- $evpath =
57
- if ($Entry -like ' %*' ) {$Entry }
58
- elseif (! $ev ) {$fullpath }
59
- else {$Entry -ireplace $ev.Value , " %$ ( $ev.Name ) %" }
60
- return [pscustomobject ]@ {
61
- Name = $Entry
62
- Path = $fullpath
63
- EnvVarPath = $evpath
64
- Commands = $cmd
65
- Precede = [string []]@ ()
66
- }
40
+ if ([string ]::IsNullOrWhiteSpace($Entry )) {return }
41
+ $fullpath = [Environment ]::ExpandEnvironmentVariables($Entry )
42
+ Write-Verbose " $Target Path: $Entry $ ( if ($Entry -ne $fullpath ){' (' + $fullpath + ' )' }) "
43
+ if (! (Test-Path $fullpath - PathType Container)) {Write-Warning " $Target Path: Entry $Entry not found!" ; return }
44
+ if ($Target -ne ' User' -and $entry.StartsWith (" $env: USERPROFILE \" )) {Write-Warning " $Target Path: Entry $entry under user profile!" ; $user += $entry ; continue }
45
+ [IO.FileInfo []]$cmd = Get-ChildItem $fullpath - File | Where-Object {$pathext -icontains $_.Extension }
46
+ if (! $cmd ) {Write-Warning " $Target Path: Entry $Entry contains no executables." ; return }
47
+ elseif ($cmd.Count -eq 1 ) {Write-Warning " $Target Path: Entry $Entry contains only one command! ($ ( $cmd [0 ].Name) )" }
48
+ else {Write-Verbose " $Target Path: Entry $Entry contains $ ( $cmd.Count ) commands." }
49
+ foreach ($c in $cmd )
50
+ {
51
+ if ($app [$c.Name ]) {$app [$c.Name ]+= $Entry }
52
+ else {[string []]$app [$c.Name ] = $Entry }
53
+ }
54
+ $ev = $evmatch | Where-Object {$Entry -match $_.Value } | Select-Object - First 1
55
+ if ($ev ) {Write-Verbose " $Target Path: $entry matches $ ( $ev.Name ) /$ ( $ev.Value ) /" }
56
+ $evpath =
57
+ if ($Entry -like ' %*' ) {$Entry }
58
+ elseif (! $ev ) {$fullpath }
59
+ else {$Entry -ireplace $ev.Value , " %$ ( $ev.Name ) %" }
60
+ return [pscustomobject ]@ {
61
+ Name = $Entry
62
+ Path = $fullpath
63
+ EnvVarPath = $evpath
64
+ Commands = $cmd
65
+ Precede = [string []]@ ()
66
+ }
67
67
}
68
68
69
69
function Get-PathDetail ([Parameter (Position = 0 , Mandatory = $true )][EnvironmentVariableTarget ]$Target )
70
70
{
71
- $path = [Environment ]::GetEnvironmentVariable(' Path' , $Target ) -split ' ;'
72
- switch ($Target )
73
- {
74
- Machine {$path | Get-PathDetail $Target }
75
- User {($Script :user + $path ) | Get-PathDetail $Target }
76
- }
71
+ $path = [Environment ]::GetEnvironmentVariable(' Path' , $Target ) -split ' ;'
72
+ switch ($Target )
73
+ {
74
+ Machine {$path | Get-PathDetail $Target }
75
+ User {($Script :user + $path ) | Get-PathDetail $Target }
76
+ }
77
77
}
78
78
79
79
function Resolve-PathConflict ([Parameter (Position = 0 , Mandatory = $true )][EnvironmentVariableTarget ]$Target ,
80
- [Parameter (Position = 1 , Mandatory = $true )][Collections.Generic.List [psobject ]]$PathDetails )
80
+ [Parameter (Position = 1 , Mandatory = $true )][Collections.Generic.List [psobject ]]$PathDetails )
81
81
{
82
- # examine conflicts
83
- if (! (Get-Command - Verb Test - Noun NewerFile)) {Set-Alias Test-NewerFile " $PSScriptRoot \Test-NewerFile.ps1" }
84
- foreach ($c in $app.Keys | Where-Object {$app .$_.Count -gt 1 })
85
- {
86
- $newest , $rest = $app [$c ]
87
- [string []]$precede = @ ()
88
- foreach ($r in $rest )
89
- {
90
- if (Test-NewerFile (Join-Path $newest $c ) (Join-Path $r $c )) {$precede += $newest ; $newest = $r }
91
- }
92
- if ($precede )
93
- {
94
- Write-Verbose " Executable conflict ${c} : $newest needs to be moved ahead of $ ( $precede -join ' , ' ) ."
95
- $npos , $rpos = 0 , 0
96
- foreach ($i in 0 .. ($precede.Length ))
97
- {
98
- if ($PathDetails [$i ].Name -eq $newest ) {$npos = $i }
99
- elseif ($rpos -ne 0 -and $precede -contains $PathDetails [$i ].Name) {$rpos = $i }
100
- }
101
- if ($npos -gt $rpos )
102
- {
103
- $n = $PathDetails [$npos ]
104
- $PathDetails.RemoveAt ($npos )
105
- $PathDetails.Insert ($rpos , $n )
106
- }
107
- }
108
- }
109
- return $PathDetails
82
+ # examine conflicts
83
+ if (! (Get-Command - Verb Test - Noun NewerFile)) {Set-Alias Test-NewerFile " $PSScriptRoot \Test-NewerFile.ps1" }
84
+ foreach ($c in $app.Keys | Where-Object {$app .$_.Count -gt 1 })
85
+ {
86
+ $newest , $rest = $app [$c ]
87
+ [string []]$precede = @ ()
88
+ foreach ($r in $rest )
89
+ {
90
+ if (Test-NewerFile (Join-Path $newest $c ) (Join-Path $r $c )) {$precede += $newest ; $newest = $r }
91
+ }
92
+ if ($precede )
93
+ {
94
+ Write-Verbose " Executable conflict ${c} : $newest needs to be moved ahead of $ ( $precede -join ' , ' ) ."
95
+ $npos , $rpos = 0 , 0
96
+ foreach ($i in 0 .. ($precede.Length ))
97
+ {
98
+ if ($PathDetails [$i ].Name -eq $newest ) {$npos = $i }
99
+ elseif ($rpos -ne 0 -and $precede -contains $PathDetails [$i ].Name) {$rpos = $i }
100
+ }
101
+ if ($npos -gt $rpos )
102
+ {
103
+ $n = $PathDetails [$npos ]
104
+ $PathDetails.RemoveAt ($npos )
105
+ $PathDetails.Insert ($rpos , $n )
106
+ }
107
+ }
108
+ }
109
+ return $PathDetails
110
110
}
111
111
112
- function Update-Path ([ Parameter ( Position = 0 , Mandatory = $true )][ EnvironmentVariableTarget ] $Target )
112
+ function Update-Path
113
113
{
114
- [Collections.Generic.List [psobject ]]$path = Get-PathDetail $Target
115
- if ($ResolveConflicts ) {$path = Resolve-PathConflict $path }
116
- if ($PSCmdlet.ShouldProcess (" $Target Path" , ' Update' ))
117
- {
118
- $newpath = ($path | Select-Object - Unique - ExpandProperty EnvVarPath) -join ' ;'
119
- Write-Verbose " New $Target Path: $newpath "
120
- Backup-Path $Target
121
- [Environment ]::SetEnvironmentVariable(' Path' , $newpath , $Target )
122
- }
114
+ [CmdletBinding (SupportsShouldProcess = $true )] Param (
115
+ [Parameter (Position = 0 , Mandatory = $true )][EnvironmentVariableTarget ]$Target
116
+ )
117
+ [Collections.Generic.List [psobject ]]$path = Get-PathDetail $Target
118
+ if ($ResolveConflicts ) {$path = Resolve-PathConflict $path }
119
+ if ($PSCmdlet.ShouldProcess (" $Target Path" , ' Update' ))
120
+ {
121
+ $newpath = ($path | Select-Object - Unique - ExpandProperty EnvVarPath) -join ' ;'
122
+ Write-Verbose " New $Target Path: $newpath "
123
+ Backup-Path $Target
124
+ [Environment ]::SetEnvironmentVariable(' Path' , $newpath , $Target )
125
+ }
123
126
}
124
127
125
128
Initialize-PathCollection
0 commit comments