it-swarm.com.de

Festlegen der Windows PowerShell-Pfadvariablen

Ich habe herausgefunden, dass das Setzen der Umgebungsvariable PATH nur die alte Eingabeaufforderung betrifft. Die PowerShell scheint unterschiedliche Umgebungseinstellungen zu haben. Wie ändere ich die Umgebungsvariablen für PowerShell (v1)?

Hinweis:

Ich möchte meine Änderungen dauerhaft machen, sodass ich sie nicht bei jedem Start von PowerShell festlegen muss. Hat PowerShell eine Profildatei? So etwas wie das Bash-Profil unter Unix?

483
Vasil

Das Ändern der tatsächlichen Umgebungsvariablen kann mit Unter Verwendung der env: namespace / drive-Informationen vorgenommen werden. Mit diesem -Code wird beispielsweise die Pfadumgebungsvariable aktualisiert:

$env:Path = "SomeRandomPath";

Es gibt Möglichkeiten, die Umgebungseinstellungen dauerhaft festzulegen, aber Wenn Sie sie nur von PowerShell aus verwenden, ist es wahrscheinlich Viel besser, Ihr Profil zu verwenden, um die Beim Start führt PowerShell alle .ps1 -Dateien aus, die im WindowsPowerShell-Verzeichnis unterMein Ordner Dokumente gefunden werden. Normalerweise haben Sie bereits eine Datei profile.ps1 Der Pfad auf meinem Computer lautet

c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
331
JaredPar

Wenn Sie während einer PowerShell-Sitzung vorübergehend an die Umgebungsvariable PATH anhängen müssen, können Sie.

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

Sie können Benutzer-/Systemumgebungsvariablen auch dauerhaft ändern (d. H. Bleiben bei Shell-Neustarts bestehen).

### Modify a system environment variable ###
[Environment]::SetEnvironmentVariable
     ("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)

### Modify a user environment variable ###
[Environment]::SetEnvironmentVariable
     ("INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User)

### Usage from comments - add to the system environment variable ###
[Environment]::SetEnvironmentVariable(
    "Path",
    [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine) + ";C:\bin",
    [EnvironmentVariableTarget]::Machine)
206
hoge

Aus der PowerShell-Eingabeaufforderung:

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

Sie sollten dann den Text sehen:

SUCCESS: Specified value was saved.

Starten Sie Ihre Sitzung neu und die Variable ist verfügbar. setx kann auch verwendet werden, um beliebige Variablen festzulegen. Geben Sie an der Eingabeaufforderung für die Dokumentation setx /? ein.

Stellen Sie sicher, dass Sie eine Kopie des vorhandenen Pfads speichern, indem Sie $env:path >> a.out in einer PowerShell-Eingabeaufforderung ausführen, bevor Sie den Pfad auf diese Weise mit dem Pfad vermischen.

48
tjb

Wie die Antwort von JeanT wollte ich eine Abstraktion um den Pfad. Im Gegensatz zu Jeants Antwort musste ich es ohne Benutzerinteraktion laufen lassen. Anderes Verhalten, das ich gesucht habe:

  • Aktualisiert $env:Path, damit die Änderung in der aktuellen Sitzung wirksam wird
  • Hält die Änderung der Umgebungsvariablen für zukünftige Sitzungen an
  • Fügt keinen doppelten Pfad hinzu, wenn derselbe Pfad bereits vorhanden ist

Falls es nützlich ist, hier ist es:

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

Check out my Gist für die entsprechende Remove-EnvPath-Funktion.

19
Michael Kropat

Obwohl die aktuell akzeptierte Antwort dahingehend funktioniert, dass die Pfadvariable permanent aus dem Kontext von PowerShell aktualisiert wird, wird die in der Windows-Registrierung gespeicherte Umgebungsvariable nicht aktualisiert.

Um dies zu erreichen, können Sie natürlich auch PowerShell verwenden:

$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

Weitere Informationen finden Sie im Blogbeitrag Verwenden Sie PowerShell, um den Umgebungspfad zu ändern.

Wenn Sie PowerShell-Community-Erweiterungen verwenden, lautet der richtige Befehl zum Hinzufügen eines Pfads zum Umgebungsvariablenpfad:

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

Alle Antworten, die auf eine dauerhafte Änderung schließen lassen, haben dasselbe Problem: Sie beschädigen den Pfadregistrierungswert.

SetEnvironmentVariable wandelt den REG_EXPAND_SZ-Wert %SystemRoot%\system32 in einen REG_SZ-Wert von C:\Windows\system32.

Alle anderen Variablen im Pfad gehen ebenfalls verloren. Das Hinzufügen neuer mit %myNewPath% funktioniert nicht mehr.

Hier ist ein Skript Set-PathVariable.ps1, das ich zur Behebung dieses Problems verwende:

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

Ich erkläre das Problem ausführlicher in einem Blogbeitrag .

9
Peter Hahndorf

Dadurch wird der Pfad für die aktuelle Sitzung festgelegt und der Benutzer wird aufgefordert, die Sitzung dauerhaft hinzuzufügen:

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

Sie können diese Funktion zu Ihrem Standardprofil (Microsoft.PowerShell_profile.ps1) hinzufügen, das sich normalerweise unter %USERPROFILE%\Documents\WindowsPowerShell befindet.

8
JeanT

Die meisten Antworten beziehen sich nicht auf UAC . Dies deckt UAC-Probleme ab.

Installieren Sie zuerst die PowerShell Community Extensions: choco install pscx über http://chocolatey.org/ (möglicherweise müssen Sie Ihre Shell-Umgebung neu starten).

Dann aktivieren Sie pscx

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

Dann benutze Invoke-Elevated 

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

Als Jonathan Leaders erwähnte hier ist es wichtig, den Befehl/das Skript erhöht auszuführen, um Umgebungsvariablen für 'machine' ändern zu können, aber das Ausführen einiger Befehle, die erhöht sind, muss nicht sein mit den Community-Erweiterungen, also möchte ich JeanTsanswer so modifizieren und erweitern, dass das Ändern von Maschinenvariablen auch dann ausgeführt werden kann, wenn das Skript selbst nicht als erhöht ausgeführt wird:

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
    }

}
5
Mehrdad Mirreza

Aufbauend auf @Michael Kropats answer habe ich einen Parameter hinzugefügt, um den neuen Pfad vor der vorhandenen Variable PATH zu setzen, und eine Prüfung, um das Hinzufügen eines nicht vorhandenen Pfads zu vermeiden:

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

MEIN VORSCHLAG IS DIESE EINE Ich habe das getestet, um C:\Oracle\x64\bin dauerhaft zu Path hinzuzufügen, und das funktioniert einwandfrei.

$ENV:PATH

Der erste Weg ist einfach zu tun:

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

Diese Änderung ist jedoch nicht von Dauer, denn $ env: path wird auf den vorherigen Wert zurückgesetzt, sobald Sie Ihr Powershell-Terminal schließen und es wieder öffnen. Das liegt daran, dass Sie die Änderung auf der Sitzungsebene und nicht auf der Quellenebene (dies ist die Registrierungsebene) vorgenommen haben. Führen Sie die folgenden Schritte aus, um den globalen Wert von $ env: path anzuzeigen:

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

oder genauer:

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

Um dies zu ändern, erfassen wir zuerst den ursprünglichen Pfad, der geändert werden muss:

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

Nun definieren wir, wie der neue Pfad aussehen soll. In diesem Fall hängen wir einen neuen Ordner an:

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

Hinweis: Stellen Sie sicher, dass $ newpath so aussieht, wie er aussehen soll. Andernfalls könnten Sie Ihr Betriebssystem beschädigen.

Wenden Sie jetzt den neuen Wert an:

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

Überprüfen Sie nun noch einmal, ob es so aussieht, wie Sie es erwarten:

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

Sie können jetzt Ihr Powershell-Terminal neu starten (oder sogar einen Neustart durchführen) und sehen, dass es nicht mehr auf den alten Wert zurückgesetzt wird. Beachten Sie, dass sich die Reihenfolge der Pfade möglicherweise in alphabetischer Reihenfolge ändert. Stellen Sie daher sicher, dass Sie die gesamte Zeile überprüfen. Zur Vereinfachung können Sie die Ausgabe in Zeilen aufteilen, indem Sie das Semikolon als Trennzeichen verwenden:

($env:path).split(“;”)
1
ali Darabi

@SBF und @Michael, bitte erlauben Sie mir, an der Party teilzunehmen.

Ich habe versucht, Ihren Code ein wenig zu optimieren, um ihn kompakter zu gestalten. 

Ich verlasse mich auf Powershells Typenzwang, bei dem Zeichenfolgen automatisch in Enumewerte konvertiert werden, sodass ich das Nachschlagewörterbuch nicht definiert habe.

Ich habe auch den Block herausgezogen, der den neuen Pfad basierend auf einer Bedingung zur Liste hinzufügt, so dass die Arbeit einmal ausgeführt und in einer Variablen zur Wiederverwendung gespeichert wird.

Sie wird dann abhängig vom Parameter $ PathContainer dauerhaft oder nur auf die Sitzung angewendet.

Wir können den Codeblock in eine Funktion oder eine ps1-Datei einfügen, die wir direkt vom Befehl Prompt aus aufrufen. Ich bin mit DevEnvAddPath.ps1 gegangen.

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;

Ich mache etwas Ähnliches für eine 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;

Bisher scheinen sie zu funktionieren. Ich freue mich über jede Rückmeldung.

Die Frage und die verschiedenen Antworten haben mich wirklich zum Nachdenken gebracht.

0
Eniola

Öffnen Sie PowerShell und führen Sie Folgendes aus:

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

In Powershell können Sie zum Verzeichnis der Umgebungsvariablen navigieren, indem Sie Folgendes eingeben:

Set-Location Env:

Dadurch gelangen Sie in das Verzeichnis Env:>. Aus diesem Verzeichnis heraus:

Geben Sie Folgendes ein, um alle Umgebungsvariablen anzuzeigen:

Env:\> Get-ChildItem

Geben Sie Folgendes ein, um eine bestimmte Umgebungsvariable anzuzeigen:

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

Geben Sie Folgendes ein, um eine Umgebungsvariable festzulegen:

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

Geben Sie Folgendes ein, um eine Umgebungsvariable zu entfernen:

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

Weitere Informationen finden Sie hier: https://docs.Microsoft.com/en-us/powershell/module/Microsoft.powershell.core/about/about_environment_variables?view=powershell-6

0
Paul Maurer