Ustawianie zmiennych środowiskowych Windows PowerShell

605

Dowiedziałem się, że ustawienie zmiennej środowiskowej PATH wpływa tylko na stary wiersz polecenia. Wygląda na to, że PowerShell ma inne ustawienia środowiska. Jak zmienić zmienne środowiskowe dla PowerShell (v1)?

Uwaga:

Chcę, aby moje zmiany były trwałe, więc nie muszę ich ustawiać za każdym razem, gdy uruchamiam PowerShell. Czy PowerShell ma plik profilu? Coś jak profil Bash na Uniksie?

Wasil
źródło
1
Chciałbym mieć profil centralny umieszczony w udziale plików. Synchronizacja to ból. Tworzenie profilu pośredniczącego za pomocą. \\ komputer \ udział \ ścieżka \ Profile.ps1 wygląda jak kludge (spróbuj Notepad $ Profile). Byłoby miło, gdyby istniał sposób na stałe zmienić zmienną automatyczną $ Profile.
Nathan Hartley
5
Żadne środowisko PATH nie wpływa również na wiersz polecenia programu PowerShell. Różni się jednak tym, że PowerShell nie akceptuje ścieżek zawartych w cudzysłowach. Rozwiązanie: usuń wszystkie otaczające cudzysłowy ( ") w zmiennej środowiskowej ścieżki
Nilzor 16.04.13
3
JEŻELI WYLESZASZ TUTAJ NA PS> v1 ... W związku z powyższym komentarzem Nilzora: użyj tego, aby usunąć wszystkie „ścieżki ze zmiennej środowiskowej PATH dla swojej sesji:$($Env:PATH).Split(';') | %{ $str += "$($_.Trim('"'));" }; $Env:PATH=$str
d3r3kk

Odpowiedzi:

477

Zmiana rzeczywistych zmiennych środowiskowych może odbywać się za pomocą env: namespace / driveinformacji. Na przykład ten kod zaktualizuje zmienną środowiskową ścieżki:

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

Istnieją sposoby na trwałe ustawienie ustawień środowiska, ale jeśli używasz ich tylko z PowerShell, prawdopodobnie lepiej jest użyć swojego profilu do zainicjowania ustawień. Podczas uruchamiania PowerShell uruchomi wszystkie znalezione pliki .ps1 w WindowsPowerShellkatalogu w folderze Moje dokumenty. Zazwyczaj masz już plik profile.ps1 . Ścieżka na moim komputerze to

C:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
JaredPar
źródło
38
$ profile to automatyczna zmienna, która wskazuje na twój profil użytkownika dla wszystkich hostów PowerShell.
JasonMArcher
16
Zauważ, że (split-path $ profile) (aby uzyskać folder zawierający) może zawierać wiele plików profilu: profile.ps1 powinny być ładowane przez wszystkie hosty, <nazwa hosta> _profile.ps1 tylko przez określonego hosta. W przypadku programu PowerShell.exe (host konsoli) jest to Microsoft.PowerShell_profile.ps1.
Richard
10
Co jeśli nie mam folderu WindowsPowerShell w moich dokumentach? Czy powinienem utworzyć folder i plik? Co powinienem umieścić w pliku, jeśli chcę dodać C:\path\to\file.extdo zmiennych środowiskowych? EDYCJA: już to znalazłem. Odpowiedź brzmi: tak, stwórz ją. Plik powinien składać się z 1 linii: $env:path += ;C:\path\to\file.ext".
Lewistrick,
7
@ Lewewick Domyślnie nie masz profilu. Postępowałem zgodnie z tymi instrukcjami, aby je utworzyć: howtogeek.com/50236/customizing-your-powershell-profile
MikeB
16
Bądź ostrożny - spowoduje to zapchanie twojej istniejącej ścieżki. $env:Path = "SomeRandomPath"; Zamiast tego - patrz @mloskot poniżej.
John Mark
626

Jeśli jakiś czas podczas sesji PowerShell musisz tymczasowo dołączyć do zmiennej środowiskowej PATH, możesz to zrobić w ten sposób:

$env:Path += ";C:\Program Files\GnuWin32\bin"
mloskot
źródło
4
+1 :: Ten jednowierszowy jest dość skuteczny dla wywołań opartych na sesjach, jak w przypadku mingw ... IE $ env: PATH + = "; c: \ MinGW \ msys \ 1.0 \ bin" ^ {some mingw bin ... }
Eddie B,
2
i jak mogę usunąć ścieżkę?
becko
11
Jeśli chcesz, aby twoja ścieżka była nazywana przed standardową, wstaw ją na początku $env:Path = "C:\MyPath;$env:Path"
Michael Freidgeim
4
**** Nie zapomnij o średniku na początku dołączanego ciągu, jak widać w komentarzu @Kevin. Jest to dość oczywiste, ale można go pominąć, jeśli po prostu skopiujesz / wkleisz kod w odpowiedzi i nie będziesz miał średnika na końcu istniejącej ścieżki. Spróbuję przesłać edycję.
Matt Goodrich,
1
@MattGoodrich Cofam się do poprzedniej wersji
Cœur
278

Można również trwale modyfikować zmienne środowiskowe użytkownika / systemu (tj. Będą trwałe podczas restartów powłoki), wykonując następujące czynności:

Zmodyfikuj systemową zmienną środowiskową

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

Zmodyfikuj zmienną środowiskową użytkownika

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

Użycie z komentarzy - dodaj do systemowej zmiennej środowiskowej

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

Rozwiązanie oparte na łańcuchach jest również możliwe, jeśli nie chcesz pisać typów

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", "Machine")
świnia
źródło
6
Jest to bardzo przydatne w przypadku systemów o ograniczonym dostępie.
h0tw1r3
14
@AndresRiofrio, Tak, to jest stałe. Użycie: [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", [EnvironmentVariableTartget::Machine) Nie zobaczysz wyniku tej zmiany, dopóki nie rozpoczniesz nowej sesji programu PowerShell. Oznacza to, że jeśli przejrzysz $ env: Path natychmiast po uruchomieniu tego polecenia, zobaczysz, co $ env: Path było przed poleceniem. Aby zaktualizować, zamknij i otwórz powłokę lub rozpocznij nową sesję.
FLGMwt
7
@FLGMwt masz literówkę, poprawne jest: [Środowisko] :: SetEnvironmentVariable („Ścieżka”, $ env: Ścieżka + ”; C: \ bin”, [EnvironmentVariableTarget] :: Maszyna)
entuzjastyczny
10
Możesz napisać ciąg „Maszyna” lub „Użytkownik” zamiast całego wyliczenia .NET. Od Technet .
bouvierr
3
Myślę, że ta odpowiedź powinna również demonstrować użycie do ustawiania zmiennej użytkownika, jak ta[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";C:\bin", "User")
Saito
63

Z wiersza polecenia programu PowerShell:

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

Powinieneś zobaczyć tekst:

SUCCESS: Specified value was saved.

Uruchom ponownie sesję, a zmienna będzie dostępna. setxmoże być również użyty do ustawienia dowolnych zmiennych. Wpisz setx /?monit w celu uzyskania dokumentacji.

Przed zadziałaniem ze swoją ścieżką w ten sposób upewnij się, że zapisałeś kopię swojej istniejącej ścieżki, wykonując $env:path >> a.outpolecenie programu PowerShell.

tjb
źródło
5
Wydaje się, że działa tylko wtedy, gdy jest „uruchomiony jako administrator”, a następnie działa tylko w przypadku konsoli PowerShell „uruchomionej jako administrator”, a nie regularnie.
matanster
12
Ojej - właśnie zostałem trafiony limitem 1024 znaków setx; na szczęście zastosowałem się do porady, aby zapisać istniejącą wartość $ end: Path. Po prostu coś, o czym należy pamiętać: superuser.com/questions/387619/…
Jonno
3
Dlaczego nie ustawić $env:PATHnajpierw, a następnie setx /m PATH "$env:PATH"zastosować lokalnie i globalnie bez restartu powłoki?
tresf
1
Miły! Mimo że setx nie jest rodzimym poleceniem cmdlet, wciąż jest znacznie lepszą i łatwiejszą do zapomnienia alternatywą dla tych okropnych, długich i skomplikowanych wywołań .NET Framework! Zaskakujące jest to, że nawet Powershell 7 wciąż nie ma oficjalnego polecenia cmdlet, które pozwala przetrwać w środowisku. Co. Czuje się jak funkcja, która powinna być zgodna z „ls”.
Jonas
27

Podobnie jak odpowiedź JeanT , chciałem abstrakcji wokół dodawania do ścieżki. W przeciwieństwie do odpowiedzi JeanT potrzebowałem, aby działała bez interakcji użytkownika. Inne zachowanie, którego szukałem:

  • Aktualizuje, $env:Pathaby zmiana obowiązywała w bieżącej sesji
  • Utrzymuje zmianę zmiennej środowiskowej dla przyszłych sesji
  • Nie dodaje zduplikowanej ścieżki, gdy ta sama ścieżka już istnieje

Jeśli jest to przydatne, oto:

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

Sprawdź moją treść dla odpowiedniej Remove-EnvPathfunkcji.

Michael Kropat
źródło
16

Chociaż bieżąca zaakceptowana odpowiedź działa w tym sensie, że zmienna ścieżki jest stale aktualizowana w kontekście programu PowerShell, w rzeczywistości nie aktualizuje zmiennej środowiskowej przechowywanej w rejestrze systemu Windows.

Aby to osiągnąć, możesz oczywiście również użyć programu PowerShell:

$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

Więcej informacji znajduje się w poście na blogu Użyj programu PowerShell, aby zmodyfikować ścieżkę środowiska

Jeśli korzystasz z rozszerzeń społeczności PowerShell, poprawnym poleceniem dodania ścieżki do ścieżki zmiennej środowiskowej jest:

Add-PathVariable "C:\NewFolderToAddToTheList" -Target Machine
gijswijs
źródło
12

Wszystkie odpowiedzi sugerujące trwałą zmianę mają ten sam problem: psują wartość rejestru ścieżki.

SetEnvironmentVariablezamienia REG_EXPAND_SZwartość %SystemRoot%\system32 na REG_SZwartość C:\Windows\system32.

Wszelkie inne zmienne na ścieżce również zostaną utracone. Dodanie nowych przy użyciu %myNewPath%już nie będzie działać.

Oto skrypt Set-PathVariable.ps1, którego używam do rozwiązania tego problemu:

 [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
 }

Wyjaśniam problem bardziej szczegółowo w poście na blogu .

Peter Hahndorf
źródło
Powinno to być: $ newPath = $ newPath -replace ";;", ";" ?
Joe Johnston,
8

To ustawia ścieżkę dla bieżącej sesji i zachęca użytkownika do jej dodania na stałe:

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

Możesz dodać tę funkcję do domyślnego profilu ( Microsoft.PowerShell_profile.ps1), zwykle znajdującego się pod adresem %USERPROFILE%\Documents\WindowsPowerShell.

JeanT
źródło
6

Opierając się na odpowiedzi @Michaela Kropat'a, dodałem parametr, aby dodać nową ścieżkę do istniejącej PATHzmiennej i sprawdzić, aby uniknąć dodania nieistniejącej ścieżki:

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 ';'
            }
        }
    }
}
SBF
źródło
5

Jak wspomniano tutaj Jonathan Leaders , ważne jest, aby uruchomić komendę / skrypt podniesiony, aby móc zmieniać zmienne środowiskowe dla „komputera” , ale uruchomienie niektórych podniesionych poleceń nie musi być wykonywane z rozszerzeniami społeczności, więc chciałbym aby zmodyfikować i rozszerzyć odpowiedź JeanT w taki sposób, że zmiana zmiennych maszynowych może być również wykonana, nawet jeśli sam skrypt nie jest uruchamiany z podwyższonym poziomem uprawnień:

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
    }

}
Mehrdad Mirreza
źródło
5

Większość odpowiedzi nie dotyczy UAC . Obejmuje to problemy z UAC.

Najpierw zainstaluj rozszerzenia społeczności PowerShell: choco install pscxprzez http://chocolatey.org/ (może być konieczne zrestartowanie środowiska powłoki).

Następnie włącz pscx

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

Następnie użyj Invoke-Elevated

Invoke-Elevated {Add-PathVariable $args[0] -Target Machine} -ArgumentList $MY_NEW_DIR
Jonathan
źródło
4

Moja propozycja jest następująca:

Przetestowałem to, aby dodać C:\oracle\x64\bindo zmiennej środowiskowej na Pathstałe i działa dobrze.

$ENV:PATH

Pierwszy sposób to po prostu zrobić:

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

Ale ta zmiana nie jest trwała. $env:pathwróci do poprzedniego stanu, jak tylko zamkniesz terminal PowerShell i ponownie go otworzysz. Jest tak, ponieważ zastosowałeś zmianę na poziomie sesji, a nie na poziomie źródła (którym jest poziom rejestru). Aby wyświetlić globalną wartość $env:path, wykonaj:

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

Lub dokładniej:

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

Teraz, aby to zmienić, najpierw przechwytujemy oryginalną ścieżkę, którą należy zmodyfikować:

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

Teraz określamy, jak powinna wyglądać nowa ścieżka. W tym przypadku dodajemy nowy folder:

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

Uwaga: Upewnij się, że $newpathwygląda tak, jak chcesz. Jeśli nie, możesz uszkodzić swój system operacyjny.

Teraz zastosuj nową wartość:

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

Teraz wykonaj ostatnią kontrolę, czy wygląda to tak, jak się spodziewasz:

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

Możesz teraz ponownie uruchomić terminal PowerShell (lub nawet zrestartować komputer) i zobaczyć, że nie przywróci on poprzedniej wartości.

Pamiętaj, że kolejność ścieżek może się zmienić, tak aby była w kolejności alfabetycznej, więc upewnij się, że sprawdziłeś całą linię. Aby to ułatwić, możesz podzielić dane wyjściowe na wiersze, używając średnika jako separatora:

($env:path).split(“;”)
Ali Darabi
źródło
3

Otwórz PowerShell i uruchom:

[Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")
Praca w
źródło
1

W programie PowerShell można przejść do katalogu zmiennych środowiskowych, wpisując:

Set-Location Env:

Spowoduje to przejście do katalogu Env:>. Z tego katalogu:

Aby zobaczyć wszystkie zmienne środowiskowe, wpisz:

Env:\> Get-ChildItem

Aby zobaczyć określoną zmienną środowiskową, wpisz:

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

Aby ustawić zmienną środowiskową, wpisz:

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

Aby usunąć zmienną środowiskową, wpisz:

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

Więcej informacji znajduje się w temacie Zmienne środowiskowe .

Paul Maurer
źródło
0

Próbowałem trochę zoptymalizować kod SBF i Michaela, aby był bardziej kompaktowy.

Opieram się na przymusie typów programu PowerShell, w którym automatycznie konwertuje ciągi znaków na wartości wyliczane, więc nie zdefiniowałem słownika wyszukiwania.

Wyciągnąłem również blok, który dodaje nową ścieżkę do listy na podstawie warunku, dzięki czemu praca jest wykonywana raz i przechowywana w zmiennej do ponownego użycia.

Następnie jest stosowany na stałe lub tylko do sesji, w zależności od $PathContainer parametru.

Możemy umieścić blok kodu w funkcji lub pliku ps1, który wywołujemy bezpośrednio z wiersza poleceń. Poszedłem z 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;

Robię coś podobnego dla 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;

Jak dotąd wydają się działać.

Eniola
źródło
0

Tylko odpowiedzi, które przekazują wartość do rejestru, wpływają na trwałą zmianę (więc większość odpowiedzi w tym wątku, w tym odpowiedź zaakceptowana, nie ma trwałego wpływu na Path).

Poniższa funkcja działa dla obu Path/ PSModulePathi User/ Systemtypów. Domyślnie doda także nową ścieżkę do bieżącej sesji.

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"
YorSubs
źródło