Skip to content

Instantly share code, notes, and snippets.

@mkropat
Last active August 2, 2024 00:35
Show Gist options
  • Save mkropat/c1226e0cc2ca941b23a9 to your computer and use it in GitHub Desktop.
Save mkropat/c1226e0cc2ca941b23a9 to your computer and use it in GitHub Desktop.
function Add-EnvPath {
param(
[Parameter(Mandatory=$true)]
[string] $Path,
[ValidateSet('Machine', 'User', 'Session')]
[string] $Container = 'Session'
)
if ($Container -ne 'Session') {
$containerMapping = @{
Machine = [EnvironmentVariableTarget]::Machine
User = [EnvironmentVariableTarget]::User
}
$containerType = $containerMapping[$Container]
$persistedPaths = [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
if ($persistedPaths -notcontains $Path) {
$persistedPaths = $persistedPaths + $Path | where { $_ }
[Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
}
}
$envPaths = $env:Path -split ';'
if ($envPaths -notcontains $Path) {
$envPaths = $envPaths + $Path | where { $_ }
$env:Path = $envPaths -join ';'
}
}
function Remove-EnvPath {
param(
[Parameter(Mandatory=$true)]
[string] $Path,
[ValidateSet('Machine', 'User', 'Session')]
[string] $Container = 'Session'
)
if ($Container -ne 'Session') {
$containerMapping = @{
Machine = [EnvironmentVariableTarget]::Machine
User = [EnvironmentVariableTarget]::User
}
$containerType = $containerMapping[$Container]
$persistedPaths = [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
if ($persistedPaths -contains $Path) {
$persistedPaths = $persistedPaths | where { $_ -and $_ -ne $Path }
[Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
}
}
$envPaths = $env:Path -split ';'
if ($envPaths -contains $Path) {
$envPaths = $envPaths | where { $_ -and $_ -ne $Path }
$env:Path = $envPaths -join ';'
}
}
function Get-EnvPath {
param(
[Parameter(Mandatory=$true)]
[ValidateSet('Machine', 'User')]
[string] $Container
)
$containerMapping = @{
Machine = [EnvironmentVariableTarget]::Machine
User = [EnvironmentVariableTarget]::User
}
$containerType = $containerMapping[$Container]
[Environment]::GetEnvironmentVariable('Path', $containerType) -split ';' |
where { $_ }
}
Export-ModuleMember -Function *
@crupest
Copy link

crupest commented Jul 28, 2018

I really like this. But I have a question about the script. Can you tell me what | where { $_ } means?

@Hrxn
Copy link

Hrxn commented Nov 2, 2019

Really great, extremely useful. Kudos.

But @mkropat, how about adding Export-ModuleMember statements at the end of the file?

No functional change, I'm aware. But it's, well, recommended. Quoting from the docs:

An Export-ModuleMember command is optional, but it is a best practice. Even if the command confirms the default values, it demonstrates the intention of the module author.

@mkropat
Copy link
Author

mkropat commented Nov 5, 2019

@Hrxn sure, that's an easy change. It's done.

@Hrxn
Copy link

Hrxn commented Nov 5, 2019

@mkropat Thank you, I appreciate it.

@simohakki
Copy link

hi, i want to call Add-EnvPath function from a powershell to add 'c:/foo', can you tell me how can i do that please ?

@Hrxn
Copy link

Hrxn commented Jan 21, 2020

@simohakki

If you use Add-EnvPath like this:
Add-EnvPath "C:\Foo" it will simply add that path to the current session, and that will work (for the current session).
Note that Add-EnvPath can take two parameters, [string] $Path and [string] $Container. If you don't set the second parameter ($Container) it will always default to Session.
If you want to add C:\Foo to either the User or System Environment var, do this:
Add-EnvPath "C:\Foo" "User"
or, alternative syntax:
Add-EnvPath -Path "C:\Foo" -Container "Machine"

Add-EnvPath (and the other functions) only work if you import them first, of course, so do this before (or in your profile, for example):
Import-Module -Name "C:\Your\Path\to\EnvPaths.psm1"

@mrlee14
Copy link

mrlee14 commented Dec 5, 2021

When adding path to machine I get error: "Requested registry access is
not allowed"... is there some workaround?

@JohnyWS
Copy link

JohnyWS commented Jan 11, 2022

@mrlee14 it always requires admin access. This script can't change that.

@brucmao
Copy link

brucmao commented May 24, 2022

@simohakki

If you use Add-EnvPath like this: Add-EnvPath "C:\Foo" it will simply add that path to the current session, and that will work (for the current session). Note that Add-EnvPath can take two parameters (参数) , [string] $Path and [string] $Container. If you don't set the second parameter (参数) ($Container) it will always default to Session. If you want to add C:\Foo to either the User or System Environment var, do this: Add-EnvPath "C:\Foo" "User" or, alternative (替代) syntax (语法) : Add-EnvPath -Path "C:\Foo" -Container "Machine"

Add-EnvPath (and the other functions) only work if you import them first, of course, so do this before (or in your profile, for example): Import-Module -Name "C:\Your\Path\to\EnvPaths.psm1"

There was an error importing the module

Import-Module: C:\Users\brucm\Documents\PowerShell\Microsoft.PowerShell_profile.ps1:2
Line |
2 | Import-Module -Name "$HOME.config\powershell\EnvPaths.psm1"

 |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | File C:\Users\brucm\.config\powershell\EnvPaths.psm1 cannot be loaded. The file
 | C:\Users\brucm\.config\powershell\EnvPaths.psm1 is not digitally signed. You cannot run this script on
 | the current system. For more information about running scripts and setting execution policy, see
 | about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.

this only can work after I execute this command with Administrator
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser

@Hrxn
Copy link

Hrxn commented May 24, 2022

@brucmao yes, this is normal. On a fresh install, ExecutionPolicy is not set, which means that PowerShell is not allowed to run any scripts.

@CuriousTreeFrog
Copy link

@mkropat Can you please tell me what is the benefit of this filtering | where { $_ } ?
Wouldn't the result be exactly the same without this?

@JohnyWS
Copy link

JohnyWS commented Nov 5, 2022

@mkropat Can you please tell me what is the benefit of this filtering | where { $_ } ?
Wouldn't the result be exactly the same without this?

It filters out any records that is regarded as "falsy" values, including empty and null values.

@anonhostpi
Copy link

Recommended change to Get-EnvPath:

function Get-EnvPath {
    param(
        [Parameter(Mandatory=$true)]
        [ValidateSet('Machine', 'User', 'Session')]
        [string] $Container
    )

    $containerMapping = @{
        Machine = [EnvironmentVariableTarget]::Machine
        User = [EnvironmentVariableTarget]::User
    }
    $containerType = $containerMapping[$Container]

    switch( $Container ){
        "Session" {
            $env:Path -split ";" |
                where { $_ }
        }
        default {
            [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';' |
                where { $_ }
        }
    }
}

@davidkhala
Copy link

instead of hardcode ";"
Would you mind replacing it with [IO.Path]::PathSeparator?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment