Windows PowerShell Milieuvariabelen instellen

Ik heb erachter gebleken dat het instellen van de PATH-omgeving Variable alleen invloed heeft op de oude opdrachtprompt. Powershell lijkt verschillende omgevingsinstellingen te hebben. Hoe verander ik de omgevingsvariabelen voor PowerShell (v1)?

Opmerking:

Ik wil mijn wijzigingen permanent maken, dus ik hoef het niet telkens in te stellen elke keer dat ik Powershell run. Heeft Powershell een profielbestand? Iets zoals Bash-profiel op Unix?


Antwoord 1, Autoriteit 100%

Wijzigen van de daadwerkelijke omgevingvariabelen kan worden gedaan door
Met behulp van de env: namespace / driveInformatie. Bijvoorbeeld dit
Code werkt de variabele Padomgeving bij:

$env:Path = "SomeRandomPath";             (replaces existing path) 
$env:Path += ";SomeRandomPath"            (appends to existing path)

Er zijn manieren om het milieu-instellingen permanent te maken, maar
Als je ze alleen van Powershell gebruikt, is het waarschijnlijk
Een stuk beter om je profiel te gebruiken om de
instellingen. Bij het opstarten loopt PowerShell een .PS1
bestanden die het vindt in de WindowsPowerShellDirectory Under
Mijn documentenmap. Typisch heb je een profiel.ps1
bestand al daar. Het pad op mijn computer is

C:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1

Antwoord 2, Autoriteit 103%

Als, wat tijd tijdens een powershell-sessie, moet je dat nodig hebben
toevoegen aan de variabele Path Milieu tijdelijk, dat kan
Doe het op deze manier:

$env:Path += ";C:\Program Files\GnuWin32\bin"

Antwoord 3, Autoriteit 53%

U kunt ook de gebruikers / systeemomgeving variabelen permanent wijzigen (d.w.z. zal persistent zijn over Shell Restarts) met het volgende:

Modificeer een systeemomgeving variabele

[Environment]::SetEnvironmentVariable
     ("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)

Wijzig een gebruikersomgeving variabele

[Environment]::SetEnvironmentVariable
     ("INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User)

Gebruik van opmerkingen – Voeg toe aan de systeemomgeving Variabele

[Environment]::SetEnvironmentVariable(
    "Path",
    [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine) + ";C:\bin",
    [EnvironmentVariableTarget]::Machine)

String-gebaseerde oplossing is ook mogelijk als u geen types wilt schrijven

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", "Machine")

Antwoord 4, Autoriteit 11%

WAARSCHUWING: Sla een kopie van uw bestaande pad op door $env:path >> a.outin een PowerShell-prompt, in het geval er iets misgaat.

Vanaf de PowerShell-prompt:

setx PATH "$env:path;\the\directory\to\add" -m

U moet dan de tekst zien:

SUCCESS: Specified value was saved.

Herstart uw sessie en de variabele is beschikbaar. setxkan ook worden gebruikt om willekeurige variabelen in te stellen. Typ setx /?bij de vraag om documentatie.


Antwoord 5, autoriteit 5%

Net als JeanT’s antwoord, wilde ik een abstractie rond het toevoegen van het pad. In tegenstelling tot het antwoord van JeanT had ik het nodig om zonder gebruikersinteractie te werken. Ander gedrag waarnaar ik op zoek was:

  • Updates $env:pathzodat de wijziging van kracht wordt in de huidige sessie
  • Houdt de wijziging van de omgevingsvariabele aan voor toekomstige sessies
  • Voegt geen dubbel pad toe als hetzelfde pad al bestaat

In het geval dat het nuttig is, hier is het:

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 ';'
    }
}

Bekijk mijn essentievoor de bijbehorende Remove-EnvPath-functie .


Antwoord 6, autoriteit 3%

Hoewel het huidige geaccepteerde antwoord werkt in die zin dat de padvariabele permanent wordt bijgewerkt vanuit de context van PowerShell, wordt de omgevingsvariabele die is opgeslagen in het Windows-register niet daadwerkelijk bijgewerkt.

Om dat te bereiken, kun je natuurlijk ook PowerShell gebruiken:

$oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
$newPath=$oldPath+’;C:\NewFolderToAddToTheList\’
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath

Meer informatie staat in blogpost Gebruik PowerShell om uw omgevingspad aan te passen

Als u PowerShell-community-extensies gebruikt, is de juiste opdracht om een pad toe te voegen aan het pad van de omgevingsvariabele:

Add-PathVariable "C:\NewFolderToAddToTheList" -Target Machine

Antwoord 7, autoriteit 2%

Alle antwoorden die een permanente wijziging suggereren, hebben hetzelfde probleem: ze breken de registerwaarde van het pad.

SetEnvironmentVariableverandert de REG_EXPAND_SZwaarde %SystemRoot%\system32in een REG_SZwaarde van C:\Windows\system32.

Alle andere variabelen in het pad gaan ook verloren. Nieuwe toevoegen met %myNewPath%werkt niet meer.

Hier is een script Set-PathVariable.ps1dat ik gebruik om dit probleem aan te pakken:

[CmdletBinding(SupportsShouldProcess=$true)]
 param(
     [parameter(Mandatory=$true)]
     [string]$NewLocation)
 Begin
 {
 #requires –runasadministrator
     $regPath = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
     $hklm = [Microsoft.Win32.Registry]::LocalMachine
     Function GetOldPath()
     {
         $regKey = $hklm.OpenSubKey($regPath, $FALSE)
         $envpath = $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
         return $envPath
     }
 }
 Process
 {
     # Win32API error codes
     $ERROR_SUCCESS = 0
     $ERROR_DUP_NAME = 34
     $ERROR_INVALID_DATA = 13
     $NewLocation = $NewLocation.Trim();
     If ($NewLocation -eq "" -or $NewLocation -eq $null)
     {
         Exit $ERROR_INVALID_DATA
     }
     [string]$oldPath = GetOldPath
     Write-Verbose "Old Path: $oldPath"
     # Check whether the new location is already in the path
     $parts = $oldPath.split(";")
     If ($parts -contains $NewLocation)
     {
         Write-Warning "The new location is already in the path"
         Exit $ERROR_DUP_NAME
     }
     # Build the new path, make sure we don't have double semicolons
     $newPath = $oldPath + ";" + $NewLocation
     $newPath = $newPath -replace ";;",""
     if ($pscmdlet.ShouldProcess("%Path%", "Add $NewLocation")){
         # Add to the current session
         $env:path += ";$NewLocation"
         # Save into registry
         $regKey = $hklm.OpenSubKey($regPath, $True)
         $regKey.SetValue("Path", $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
         Write-Output "The operation completed successfully."
     }
     Exit $ERROR_SUCCESS
 }

Ik leg het probleem in meer detail uit in een blogpost .


Antwoord 8

Hiermee stelt u het pad in voor de huidige sessie en vraagt ​​de gebruiker om deze permanent toe te voegen:

function Set-Path {
    param([string]$x)
    $Env:Path+= ";" +  $x
    Write-Output $Env:Path
    $write = Read-Host 'Set PATH permanently ? (yes|no)'
    if ($write -eq "yes")
    {
        [Environment]::SetEnvironmentVariable("Path",$env:Path, [System.EnvironmentVariableTarget]::User)
        Write-Output 'PATH updated'
    }
}

U kunt deze functie toevoegen aan uw standaardprofiel, (Microsoft.PowerShell_profile.ps1), meestal op %USERPROFILE%\Documents\WindowsPowerShell.


Antwoord 9

Gebouw op @michael kropat’s antwoord Ik heb een parameter toegevoegd om het nieuwe pad naar de Bestaande PATHvariabele en een cheque om de toevoeging van een niet-bestaand pad te voorkomen:

function Add-EnvPath {
    param(
        [Parameter(Mandatory=$true)]
        [string] $Path,
        [ValidateSet('Machine', 'User', 'Session')]
        [string] $Container = 'Session',
        [Parameter(Mandatory=$False)]
        [Switch] $Prepend
    )
    if (Test-Path -path "$Path") {
        if ($Container -ne 'Session') {
            $containerMapping = @{
                Machine = [EnvironmentVariableTarget]::Machine
                User = [EnvironmentVariableTarget]::User
            }
            $containerType = $containerMapping[$Container]
            $persistedPaths = [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
            if ($persistedPaths -notcontains $Path) {
                if ($Prepend) {
                    $persistedPaths = ,$Path + $persistedPaths | where { $_ }
                    [Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
                }
                else {
                    $persistedPaths = $persistedPaths + $Path | where { $_ }
                    [Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
                }
            }
        }
        $envPaths = $env:Path -split ';'
        if ($envPaths -notcontains $Path) {
            if ($Prepend) {
                $envPaths = ,$Path + $envPaths | where { $_ }
                $env:Path = $envPaths -join ';'
            }
            else {
                $envPaths = $envPaths + $Path | where { $_ }
                $env:Path = $envPaths -join ';'
            }
        }
    }
}

Antwoord 10

Mijn suggestie is deze:

Ik heb dit getest om C:\oracle\x64\binpermanent toe te voegen aan de omgevingsvariabele Pathen dit werkt prima.

$ENV:PATH

De eerste manier is om gewoon te doen:

$ENV:PATH=”$ENV:PATH;c:\path\to\folder”

Maar deze wijziging is niet permanent. $env:pathwordt standaard teruggezet naar wat het was zodra u uw PowerShell-terminal sluit en opnieuw opent. Dat komt omdat u de wijziging op sessieniveau hebt toegepast en niet op bronniveau (dat is het registerniveau). Ga als volgt te werk om de globale waarde van $env:pathte bekijken:

Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH

Of meer specifiek:

(Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path

Om dit nu te veranderen, leggen we eerst het oorspronkelijke pad vast dat moet worden gewijzigd:

$oldpath = (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path

Nu definiëren we hoe het nieuwe pad eruit moet zien. In dit geval voegen we een nieuwe map toe:

$newpath = “$oldpath;c:\path\to\folder”

Opmerking: zorg ervoor dat het $newpatheruitziet zoals je wilt dat het eruitziet. Als dat niet het geval is, kunt u uw besturingssysteem beschadigen.

Pas nu de nieuwe waarde toe:

Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH -Value $newPath

Voer nu nog een laatste controle uit of het eruitziet zoals je verwacht:

(Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path

U kunt nu uw PowerShell-terminal opnieuw opstarten (of zelfs de machine opnieuw opstarten) en zien dat deze niet meer teruggaat naar de oude waarde.

Houd er rekening mee dat de volgorde van de paden kan veranderen, zodat deze in alfabetische volgorde staat, dus zorg ervoor dat u de hele regel controleert. Om het gemakkelijker te maken, kunt u de uitvoer in rijen splitsen door de puntkomma als scheidingsteken te gebruiken:

($env:path).split(“;”)

Antwoord 11

Binnen PowerShell kan men naar de map met omgevingsvariabelen navigeren door te typen:

Set-Location Env:

Dit brengt u bij de Env:> map. Vanuit deze map:

Als u alle omgevingsvariabelen wilt zien, typt u:

Env:\> Get-ChildItem

Als u een specifieke omgevingsvariabele wilt zien, typt u:

Env:\> $Env:<variable name>, e.g. $Env:Path

Om een omgevingsvariabele in te stellen, typt u:

Env:\> $Env:<variable name> = "<new-value>", e.g. $Env:Path="C:\Users\"

Als u een omgevingsvariabele wilt verwijderen, typt u:

Env:\> remove-item Env:<variable name>, e.g. remove-item Env:SECRET_KEY

Meer informatie staat in Over omgevingsvariabelen.


Antwoord 12

Zoals Jonathan Leadershieris het belangrijk om de opdracht/het script verhoogd uit te voeren om de omgevingsvariabelen voor ‘machine’te kunnen wijzigen, maar het uitvoeren van sommige verhoogde opdrachten hoeft niet te worden gedaan met de Community-extensies, dus ik wil JeanT’sbeantwoordzodanig dat het wijzigen van machinevariabelen ook kan worden uitgevoerd, zelfs als het script zelf niet verhoogd wordt uitgevoerd:

function Set-Path ([string]$newPath, [bool]$permanent=$false, [bool]$forMachine=$false )
{
    $Env:Path += ";$newPath"
    $scope = if ($forMachine) { 'Machine' } else { 'User' }
    if ($permanent)
    {
        $command = "[Environment]::SetEnvironmentVariable('PATH', $env:Path, $scope)"
        Start-Process -FilePath powershell.exe -ArgumentList "-noprofile -command $Command" -Verb runas
    }
}

Antwoord 13

De meeste antwoorden hebben geen betrekking op UAC. Dit dekt UAC-problemen.

Installeer eerst PowerShell Community Extensions: choco install pscxvia http://chocolatey.org/(mogelijk moet u uw shell-omgeving opnieuw opstarten).

Schakel vervolgens pscx in

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #allows scripts to run from the interwebs, such as pcsx

Gebruik vervolgens Invoke-Elevated

Invoke-Elevated {Add-PathVariable $args[0] -Target Machine} -ArgumentList $MY_NEW_DIR

Antwoord 14

maak jezelf geen zorgen, wil een eenvoudige, éénregelige oplossing om een permanenteomgevingsvariabele toe te voegen (open powershell in verhoogde modus):

[Environment]::SetEnvironmentVariable("NewEnvVar", "NewEnvValue", "Machine")

Sluit de sessie en open deze opnieuw om dingen voor elkaar te krijgen


voor het geval u dat wilt wijzigen/wijzigen:

[Environment]::SetEnvironmentVariable("oldEnvVar", "NewEnvValue", "Machine")


voor het geval u dat wilt verwijderen/verwijderen:

[Environment]::SetEnvironmentVariable("oldEnvVar", "", "Machine")

Antwoord 15

Voor alle duidelijkheid, de Windows-manier van de jaren 90: klik op Start, klik met de rechtermuisknop op Deze pcen kies Eigenschappenen selecteer vervolgens Geavanceerde systeeminstellingenen selecteer vervolgens in het dialoogvenster dat verschijnt Omgevingsvariabelenen dubbelklik in de lijst op PATHen gebruik vervolgens de Nieuwe, Bewerken, Move Upen Move Downwerken allemaal nog steeds voor het wijzigen van het PATH. Power shell en de rest van Windows krijgen alles wat je hier instelt.

Ja, u kunt deze nieuwe methoden gebruiken, maar de oude werkt nog steeds. En op het basisniveau zijn alle permanente wijzigingsmethoden gecontroleerde manieren om uw registerbestanden te bewerken.


Antwoord 16

Alleen de antwoorden die de waarde in het register duwen, zijn van invloed op een permanentewijziging (dus de meeste antwoorden in deze discussie, inclusief het geaccepteerde antwoord, hebben nietpermanent effect op het Path).

De volgende functie werkt voor zowel Path/ PSModulePathals voor User/ System-typen. Het zal ook standaard het nieuwe pad aan de huidige sessie toevoegen.

function AddTo-Path {
    param ( 
        [string]$PathToAdd,
        [Parameter(Mandatory=$true)][ValidateSet('System','User')][string]$UserType,
        [Parameter(Mandatory=$true)][ValidateSet('Path','PSModulePath')][string]$PathType
    )
    # AddTo-Path "C:\XXX" "PSModulePath" 'System' 
    if ($UserType -eq "System" ) { $RegPropertyLocation = 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' }
    if ($UserType -eq "User"   ) { $RegPropertyLocation = 'HKCU:\Environment' } # also note: Registry::HKEY_LOCAL_MACHINE\ format
    $PathOld = (Get-ItemProperty -Path $RegPropertyLocation -Name $PathType).$PathType
    "`n$UserType $PathType Before:`n$PathOld`n"
    $PathArray = $PathOld -Split ";" -replace "\\+$", ""
    if ($PathArray -notcontains $PathToAdd) {
        "$UserType $PathType Now:"   # ; sleep -Milliseconds 100   # Might need pause to prevent text being after Path output(!)
        $PathNew = "$PathOld;$PathToAdd"
        Set-ItemProperty -Path $RegPropertyLocation -Name $PathType -Value $PathNew
        Get-ItemProperty -Path $RegPropertyLocation -Name $PathType | select -ExpandProperty $PathType
        if ($PathType -eq "Path") { $env:Path += ";$PathToAdd" }                  # Add to Path also for this current session
        if ($PathType -eq "PSModulePath") { $env:PSModulePath += ";$PathToAdd" }  # Add to PSModulePath also for this current session
        "`n$PathToAdd has been added to the $UserType $PathType"
    }
    else {
        "'$PathToAdd' is already in the $UserType $PathType. Nothing to do."
    }
}
# Add "C:\XXX" to User Path (but only if not already present)
AddTo-Path "C:\XXX" "User" "Path"
# Just show the current status by putting an empty path
AddTo-Path "" "User" "Path"

Antwoord 17

Open PowerShell en voer het volgende uit:

[Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")

Antwoord 18

Ik heb geprobeerd SBF’sen Michael’scode een beetje om het compacter te maken.

Ik vertrouw op PowerShell’s type dwang waarbij het automatisch tekenreeksen converteert naar enum-waarden, dus ik heb het opzoekwoordenboek niet gedefinieerd.

Ik heb ook het blok verwijderd dat het nieuwe pad aan de lijst toevoegt op basis van een voorwaarde, zodat het werk eenmalig wordt gedaan en wordt opgeslagen in een variabele voor hergebruik.

Het wordt dan permanent of alleen op de sessie toegepast, afhankelijk van de parameter $PathContainer.

We kunnen het codeblok in een functie of een ps1-bestand plaatsen dat we rechtstreeks vanaf de opdrachtprompt aanroepen. Ik ging met DevEnvAddPath.ps1.

param(
    [Parameter(Position=0,Mandatory=$true)][String]$PathChange,
    [ValidateSet('Machine', 'User', 'Session')]
    [Parameter(Position=1,Mandatory=$false)][String]$PathContainer='Session',
    [Parameter(Position=2,Mandatory=$false)][Boolean]$PathPrepend=$false
)
[String]$ConstructedEnvPath = switch ($PathContainer) { "Session"{${env:Path};} default{[Environment]::GetEnvironmentVariable('Path', $containerType);} };
$PathPersisted = $ConstructedEnvPath -split ';';
if ($PathPersisted -notcontains $PathChange) {
    $PathPersisted = $(switch ($PathPrepend) { $true{,$PathChange + $PathPersisted;} default{$PathPersisted + $PathChange;} }) | Where-Object { $_ };
    $ConstructedEnvPath = $PathPersisted -join ";";
}
if ($PathContainer -ne 'Session') 
{
    # Save permanently to Machine, User
    [Environment]::SetEnvironmentVariable("Path", $ConstructedEnvPath, $PathContainer);
}
# Update the current session
${env:Path} = $ConstructedEnvPath;

Ik doe iets soortgelijks voor een DevEnvRemovePath.ps1.

param(
    [Parameter(Position=0,Mandatory=$true)][String]$PathChange,
    [ValidateSet('Machine', 'User', 'Session')]
    [Parameter(Position=1,Mandatory=$false)][String]$PathContainer='Session'
)
[String]$ConstructedEnvPath = switch ($PathContainer) { "Session"{${env:Path};} default{[Environment]::GetEnvironmentVariable('Path', $containerType);} };
$PathPersisted = $ConstructedEnvPath -split ';';
if ($PathPersisted -contains $PathChange) {
    $PathPersisted = $PathPersisted | Where-Object { $_ -ne $PathChange };
    $ConstructedEnvPath = $PathPersisted -join ";";
}
if ($PathContainer -ne 'Session') 
{
    # Save permanently to Machine, User
    [Environment]::SetEnvironmentVariable("Path", $ConstructedEnvPath, $PathContainer);
}
# Update the current session
${env:Path} = $ConstructedEnvPath;

Tot nu toe lijken ze te werken.


Antwoord 19

Veel voorbeelden van toevoegen of overschrijven. Hier is een voorbeeld van het toevoegen van een pad op powershell voor Linux, Ubuntu 18.04 met pwsh7.1.3

$ENV:PATH = "/home/linuxbrew/.linuxbrew/bin:$ENV:PATH"

Ik voeg specifiek de linuxbrew (homebrew voor linux) bin directory toe om voorrang te krijgen op het geïnstalleerde systeem. Het hielp bij het oplossen van een probleem dat ik had en hoewel dit de meest behulpzame plek was, liet het me ook “experimenteren”.

Merk op dat de :een Linux-padscheidingsteken is, terwijl je in Windows (of in ieder geval mijn Windows) normaal gesproken ;voor powershell zou gebruiken.

Other episodes