env2.psm1

function Set-Env {
  <#
  .SYNOPSIS
  Set a permanent environment variable on the user, process, or system.

  .PARAMETER Name
  The name of the environment variable to be modified.

  .PARAMETER Value
  The value that will be written to the environment variable.

  .PARAMETER Target
  The scope of the environment variable setting (user, process, machine).
  Defaults to User.

  .EXAMPLE
  Set a user-specific environment variable.
  PS> Set-Env -Name MY_FIRST_NAME -Value Trevor

  .EXAMPLE
  Set a machine-wide environment variable
  PS> Set-Env -Name MY_LAST_NAME -Value Sullivan -Target Machine
  #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [string]
    $Name,
    [Parameter(Mandatory = $false)]
    [System.EnvironmentVariableTarget]
    $Target = [System.EnvironmentVariableTarget]::User,
    [Parameter(Mandatory = $true)]
    [string]
    $Value
  )
  [System.Environment]::SetEnvironmentVariable($Name, $Value, $Target)
}

function Get-Env {
  <#
  .SYNOPSIS
  Retrieves the value of a Windows environment variable.

  .PARAMETER Name
  The name of the environment variable, whose value will be returned.

  .PARAMETER Target
  The scope of the environment variable, whose value will be returned.
  Defaults to User.
  #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [string] $Name,
    [Parameter(Mandatory = $false)]
    $Target = [System.EnvironmentVariableTarget]::User
  )
  [System.Environment]::GetEnvironmentVariable($Name, $Target)
}

function Add-EnvPath {
  <#
  .SYNOPSIS
  Adds a filesystem path to the $env:PATH environment variable on Windows.

  .PARAMETER Path
  The filesystem path that will be added to the $env:PATH environment variable.
  Defaults to the current directory.
  
  .PARAMETER Target
  The scope of the PATH environment variable: user, process, or machine.
  Defaults to User.

  .EXAMPLE
  Add the current directory to the user's PATH environment variable.
  PS> Add-EnvPath

  .EXAMPLE
  Add a specific directory to the user's PATH environment variable.
  PS> Add-EnvPath -Path 'c:\test 123'

  .EXAMPLE
  Add the current directory to the machine-wide PATH environment variable.
  PS> Add-EnvPath -Target Machine

  .EXAMPLE
  Add a specific directory to the machine-wide PATH environment variable.
  PS> Add-EnvPath -Path 'c:\test 123' -Target Machine
  #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $false)]
    [string] $Path = (Get-Location -PSProvider Filesystem),
    [Parameter(Mandatory = $false)]
    [System.EnvironmentVariableTarget]
    $Target = [System.EnvironmentVariableTarget]::User
  )
  $Value = Get-Env -Target $Target -Name Path
  if ($Value.Split(';') -notcontains $Path) {
    $Value += ';{0}' -f $Path
    Set-Env -Target $Target -Name Path -Value $Value
  }
  else {
    Write-Verbose -Message ('Path is already present in PATH variable for scope {0}' -f $Target)
  }
}

function Remove-EnvPath {
  <#
  .SYNOPSIS
  Removes a filesystem path from the PATH environment variable on Windows.

  .PARAMETER Path
  The filesystem path that will be removed from the PATH environment variable.
  Defaults to the current filesystem path.

  .PARAMETER Target
  The scope of the PATH environment variable that will be modified: user, process, or machine.
  Defaults to User.

  .EXAMPLE
  Remove the current directory from the user's PATH environment variable.
  PS> Remove-EnvPath
  
  .EXAMPLE
  Remove a specific directory from the user's PATH environment variable.
  PS> Remove-EnvPath -Path 'c:\test 123'
  
  .EXAMPLE
  Remove the current directory from the user's PATH environment variable.
  PS> Remove-EnvPath -Target Machine

  .EXAMPLE
  Remove a specific directory from the machine-wide PATH environment variable.
  PS> Remove-EnvPath -Path 'c:\test 123' -Target Machine
  #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $false)]
    [string] $Path = (Get-Location -PSProvider Filesystem),
    [Parameter(Mandatory = $false)]
    [System.EnvironmentVariableTarget] $Target = [System.EnvironmentVariableTarget]::User
  )

  $Value = Get-Env -Target $Target -Name Path
  $List = [System.Collections.ArrayList]::new();
  $Value.Split(';').ForEach({ $null = $List.Add($PSItem) })
  if ($List -contains $Path) {
    $List.Remove($Path)
    Set-Env -Name Path -Target $Target -Value ($List -join ';')
    Write-Verbose -Message ('Removed path {0} from PATH environment variable for {1} scope' -f $Path, $Target.ToString())
  }
  else {
    Write-Verbose -Message ('Path {0} not found in PATH environment variable for {1} scope' -f $Path, $Target.ToString())
  }
}