EnvironmentVariableItems.psm1
<#
.SYNOPSIS Adds an environment variable for given name, value, scope (default; 'process') and separator (';') and optional position. .EXAMPLE Insert 'C:\foo' as the last but one item in $env:Path variable PS> Add-EnvironmentVariableItem -Name path -Value c:\foo -Scope User -Position -1 -WhatIf What if: Current Value: C:\Users\michaelf\AppData\Local\Microsoft\WindowsApps;C:\Users\michaelf\AppData\Local\Programs\Microsoft VS Code\bin New value: C:\Users\michaelf\AppData\Local\Microsoft\WindowsApps;c:\foo;C:\Users\michaelf\AppData\Local\Programs\Microsoft VS Code\bin .EXAMPLE Add 'cake' as last item of $env:foo PS> aevi foo cake -Scope User -Separator '#' -whatif What if: Current Value: foo#bar#cup New value: foo#bar#cup#cake #> function Add-EnvironmentVariableItem { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')] param ( [Parameter( Mandatory, Position = 0 )] [ValidatePattern("[^=]+")] [String] $Name, [Parameter( Mandatory, Position = 1 )] [String] $Value, [Parameter()] [System.EnvironmentVariableTarget] $Scope = [System.EnvironmentVariableTarget]::Process, [Parameter()] [String] $Separator = ';', [Parameter()] [int] $Position ) process { $evis = Get-EnvironmentVariableItems $Name $Scope $Separator if ($PSBoundParameters.ContainsKey('Position')) { $result = $evis.AddItem($Value, $Position) -ne $False } else { $result = $evis.AddItem($Value) -ne $False } if ($result -ne $False) { $s = GetWhatIf if ($PSCmdlet.ShouldProcess($s, '', '')){ $evis.UpdateEnvironmentVariable() $evis } } else { return } } } <# .SYNOPSIS Gets an EnvironmentVariableItems object for a given name, scope (default; 'process') and separator (';'). .EXAMPLE Get machine's $env:Path EnvironmentVariableItems object PS>Get-EnvironmentVariableItems -Name Path -Scope Machine Name : Path Scope : Machine Separator : ; Value : C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH \;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-Static;C:\ProgramData\chocolatey\bin;C:\Program Files\PowerShell\7\;C:\Program Files\Git\cmd Items : {C:\WINDOWS\system32, C:\WINDOWS, C:\WINDOWS\System32\Wbem, C:\WINDOWS\System32\WindowsPowerShell\v1.0\…} .EXAMPLE Show index of $env:PSModulePath items PS>(gevis PSModulePath).ShowIndex() 0: C:\Users\michaelf\Documents\PowerShell\Modules 1: C:\Program Files\PowerShell\Modules 2: c:\program files\powershell\7\Modules 3: H:\lib\pow\mod 4: C:\Program Files\WindowsPowerShell\Modules 5: C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules 6: N:\lib\pow\mod #> function Get-EnvironmentVariableItems { [CmdletBinding()] param ( [Parameter(Mandatory)] [String] $Name, [Parameter()] [System.EnvironmentVariableTarget] $Scope = [System.EnvironmentVariableTarget]::Process, [Parameter()] [String] $Separator = ';' ) process { New-EnvironmentVariableItems-Object $Name $Scope $Separator } } function GetWhatIf() { @" Current Value: $((Get-EnvironmentVariable -Name $Name -Scope $Scope).ToString()) New value: $($evis.ToString()) "@ } function New-EnvironmentVariableItems-Object { param ( [Parameter(Mandatory)] [String] $Name, [Parameter()] [System.EnvironmentVariableTarget] $Scope = [System.EnvironmentVariableTarget]::Process, [Parameter()] [String] $Separator = ';' ) process { $value = (Get-EnvironmentVariable -Name $Name -Scope $Scope).Value $items = $value -split $Separator $obj = [PSCustomObject]@{ Name = $Name Scope = $Scope Separator = $Separator Value = $Value Items = [System.Collections.ArrayList] $items } $obj | Add-Member ScriptMethod AddItem { [CmdletBinding()] param ( [Parameter( Mandatory, Position = 0 )] [String] $Value, [Parameter()] [int] $Position ) process { if ($PSBoundParameters.ContainsKey('Position')) { if (($ind = $this.GetIndexByPosition($Position)) -is [int]) { $this.Items.insert($ind, $Value) } else { return $False } } else { $this.Items.add($Value) } } } -Force # method returns actual index value (negative value counts back through array) unless 'Position' is out of range $obj | Add-Member ScriptMethod GetIndexByPosition { [CmdletBinding()] param ( [Parameter( Mandatory, Position = 0 )] [int] $Position ) $len = $this.Items.count if ($Position -lt $len -and $(-($Position) -le $len)) { if ($Position -lt 0) { $len + $Position } else { $Position } } else { Write-Host "Position $Position is out of range" } } -Force $obj | Add-Member ScriptMethod RemoveItemByPosition { [CmdletBinding()] param ( [Parameter(Mandatory)] [int] $Position ) process { if (($ind = $this.GetIndexByPosition($Position)) -is [int]) { $this.Items.RemoveAt($ind) } else { return $False } } } -Force $obj | Add-Member ScriptMethod RemoveItemByValue { [CmdletBinding()] param ( [Parameter( Mandatory, Position = 0 )] [String] $Value ) process { if (($this.Items.IndexOf($Value)) -ge 0) { $this.Items.Remove($Value) } else { Write-Host "Value $Value not found" return $False } } } -Force $obj | Add-Member ScriptMethod ShowIndex { process { for ($i = 0; $i -lt $this.Items.count; $i++) { Write-Host "${i}: $($this.Items[$i].ToString())" } Write-Host } } -Force $obj | Add-Member ScriptMethod ToString { $s = '' for ($i = 0; $i -lt $this.Items.count; $i++) { if ($i) { $s += $this.Separator} $s += $this.Items[$i] } $s } -Force $obj | Add-Member ScriptMethod UpdateEnvironmentVariable { $this.Value = $this.ToString() Set-EnvironmentVariable -Name $this.Name -value $this.Value -scope $this.Scope | Out-Null } -Force return $obj } } <# .SYNOPSIS Adds an environment variable for given name, value and scope (default; 'process') and separator (';') and optional position. .EXAMPLE Remove 'c:\foo' from $env:Path variable PS> Remove-EnvironmentVariableItem -Name path -Value 'c:\foo' -Scope User -WhatIf What if: Current Value: C:\Users\michaelf\AppData\Local\Microsoft\WindowsApps;c:\foo;C:\Users\michaelf\AppData\Local\Programs\Microsoft VS Code\bin New value: C:\Users\michaelf\AppData\Local\Microsoft\WindowsApps;C:\Users\michaelf\AppData\Local\Programs\Microsoft VS Code\bin .EXAMPLE Show index and remove item from $env:foo variable PS> (Get-EnvironmentVariableItems -Name foo -Scope User -Separator '#').ShowIndex() 0: foo 1: cake 2: bar 3: cup PS> revi foo 1 -Scope User -Separator '#' -WhatIf What if: Current Value: foo#cake#bar#cup New value: foo#bar#cup #> function Remove-EnvironmentVariableItem { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')] param ( [Parameter( Mandatory, Position = 0 )] [ValidatePattern("[^=]+")] [String] $Name, [Parameter( Mandatory, ParameterSetName = 'ByValue', Position = 1 )] [String] $Value, [Parameter( ParameterSetName = 'ByPosition', Position = 1, Mandatory )] [int] $Position, [Parameter()] [System.EnvironmentVariableTarget] $Scope = [System.EnvironmentVariableTarget]::Process, [Parameter()] [String] $Separator = ";" ) process { $evis = Get-EnvironmentVariableItems $Name $Scope $Separator if ($PSCmdlet.ParameterSetName -eq 'ByPosition') { $result = $evis.RemoveItemByPosition($Position) -ne $False } elseif ($PSCmdlet.ParameterSetName -eq 'ByValue') { $result = $evis.RemoveItemByValue($Value) -ne $False } if ($result -ne $False) { $s = GetWhatIf if ($PSCmdlet.ShouldProcess($s, '', '')){ #Set-EnvironmentVariable -Name $Name -value $evis.ToString() -scope $Scope | Out-Null $evis.UpdateEnvironmentVariable() $evis } } else { return } } } New-Alias -Name aevi -Value Add-EnvironmentVariableItem New-Alias -Name gevis -Value Get-EnvironmentVariableItems New-Alias -Name revi -Value Remove-EnvironmentVariableItem Export-ModuleMember -Alias * -Function * |