Indstilling af Windows PowerShell-sti-variabel

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har fundet ud af, at indstilling af PATH-miljøvariablen kun påvirker den gamle kommandoprompt. PowerShell synes at have forskellige miljøindstillinger. Hvordan ændrer jeg miljøvariablerne til PowerShell (v1)?


Bemærk:


Jeg vil gerne lave mine ændringer permanent, så jeg behøver ikke at angive det hver gang jeg kører PowerShell. Har PowerShell en profilfil? Noget som Bash-profil på Unix?

Bedste reference


Ændring af de faktiske miljøvariabler kan udføres af
bruger oplysningerne env: namespace / drive. For eksempel dette
kode opdaterer sti miljøvariablen:


$env:Path = "SomeRandomPath";


Der er måder at gøre miljøindstillingerne permanente, men
Hvis du kun bruger dem fra PowerShell, er det nok
meget bedre at bruge din profil til at starte
indstillinger. Ved opstart vil PowerShell køre nogen .ps1
filer den finder i WindowsPowerShell-biblioteket under
Min Dokumenter-mappe. Normalt har du en profile.ps1
filen allerede der. Stien på min computer er


c:UsersJaredParDocumentsWindowsPowerShellprofile.ps1

Andre referencer 1


Hvis du skal bruge en tid under en PowerShell-session
Du kan midlertidigt ændre PATH-miljøvariablen, du kan
gør det på denne måde:


$env:Path += ";C:Program FilesGnuWin32in"

Andre referencer 2


Du kan også permanent ændre bruger-/systemmiljøvariabler permanent (dvs. vil være vedvarende på tværs af shell genstart) med følgende


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

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

### from comments ###
### Usage from comments - Add to the system environment variable ###
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:in", [EnvironmentVariableTarget]::Machine)

Andre referencer 3


Fra PowerShell-prompten:


setx PATH "$env:path;	hedirectory	oadd" -m


Du skal så se teksten:


SUCCESS: Specified value was saved.


Genstart din session, og variablen vil være tilgængelig. setx kan også bruges til at indstille vilkårlig variabler. Skriv setx /? ved spørgsmålet om dokumentation.


Sørg for, at du gemmer en kopi af din eksisterende sti ved at gøre $env:path >> a.out i en PowerShell-prompe, før du ringer med din vej på denne måde.

Andre referencer 4


Selv om det nuværende accepterede svar virker i den forstand, at sti-variablen permanent opdateres fra PowerShells kontekst, opdateres den ikke faktisk miljøvariablen, der er gemt i Windows-registreringsdatabasen.
For at opnå det kan du selvfølgelig også bruge PowerShell:


$oldPath=(Get-ItemProperty -Path 'Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment' -Name PATH).Path

$newPath=$oldPath+’;C:NewFolderToAddToTheList’

Set-ItemProperty -Path 'Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment' -Name PATH –Value $newPath


Mere info her: http://blogs.technet.com/b/heyscriptingguy/archive/2011/07/23/use-powershell-to-modify-your-environmental-path.aspx[43]


Hvis du bruger PowerShell-fællesskabsudvidelser, er den korrekte kommando for at tilføje en sti til miljøvariabanen:


Add-PathVariable "C:NewFolderToAddToTheList" -Target Machine

Andre referencer 5


Som JeanT 's svar ønskede jeg en abstraktion omkring at tilføje til stien. I modsætning til JeanT' s svar havde jeg brug for at køre uden brugerinteraktion. Anden opførsel, jeg ledte efter:



  • Opdateringer $env:Path, så ændringen træder i kraft i den aktuelle session

  • Fortsætter ændringen af ​​miljøvariablen til fremtidige sessioner

  • Tilføj ikke en duplikatsti, når den samme sti allerede eksisterer



Hvis det er nyttigt, er det her:


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


Tjek mit indhold for den tilsvarende Remove-EnvPath funktion. [45]

Andre referencer 6


Dette angiver stien til den aktuelle session og beder brugeren om at tilføje den permanent:


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


Du kan tilføje denne funktion til din standardprofil, (Microsoft.PowerShell\_profile.ps1), normalt placeret på \%USERPROFILE\%DocumentsWindowsPowerShell.

Andre referencer 7


Alle svarene, der tyder på en permanent ændring, har det samme problem: De bryder stien registreringsværdien.


SetEnvironmentVariable ændrer værdien REG\_EXPAND\_SZ \%SystemRoot\%system32 til en REG\_SZ værdi på C:Windowssystem32.


Eventuelle andre variabler i stien går også tabt. Tilføjelse af nye der bruger \%myNewPath\% vil ikke virke mere.


Her er et script Set-PathVariable.ps1, som jeg bruger til at løse dette problem:


 [CmdletBinding(SupportsShouldProcess=$true)]
 param(
     [parameter(Mandatory=$true)]
     [string]$NewLocation)

 Begin
 {

 #requires –runasadministrator

     $regPath = "SYSTEMCurrentControlSetControlSession ManagerEnvironment"
     $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
 }


Jeg forklarer problemet mere detaljeret i et blogindlæg. [46]

Andre referencer 8


Som Jonathan Leaders nævnte her, er det vigtigt at køre kommandoen/scriptet forhøjet for at kunne ændre miljøvariabler for 'maskine' , men at køre nogle kommandoer forhøjet skal ikke gøres med Fællesskabet Udvidelser, så jeg gerne vil ændre og udvide JeanT's svar på en måde, at skiftende maskinvariabler også kan udføres selvom selve scriptet ikke løber højt:


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
    }

}

Andre referencer 9


De fleste svar er ikke adresseret til UAC. Dette dækker UAC-spørgsmål. [51]


Først installerer PowerShell Community Extensions: choco install pscx via http://chocolatey.org/(du skal muligvis genstarte dit shell miljø). [52]


Aktivér derefter pscx


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


Brug derefter Invoke-Elevated


Invoke-Elevated {Add-PathVariable $args[0] -Target Machine} -ArgumentList $MY\_NEW\_DIR

Andre referencer 10


På baggrund af @Michael Kropats svar tilføjede jeg en parameter for at udfylde den nye sti til den eksisterende variabel PATH og en check for at undgå tilføjelsen af ​​en ikke eksisterende sti:


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

Andre referencer 11


Mit forslag er dette
Jeg har testet dette for at tilføje C: \ Oracle \ x64 \ bin til Path permanent, og det virker fint.


$ENV:PATH


Den første måde er simpelthen at gøre:


$ENV:PATH=”$ENV:PATH;c:path	ofolder”


Men denne ændring er ikke permanent, $ env: stien går som standard tilbage til, hvad det var før, så snart du lukker din powershell terminal og genåbner den igen. Det skyldes, at du har anvendt ændringen på sessionsniveau og ikke på kildeniveau (hvilket er registreringsniveauet). For at se den globale værdi af $ env: sti, gør:


Get-ItemProperty -Path ‘Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment’ -Name PATH


eller mere specifikt:


(Get-ItemProperty -Path ‘Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment’ -Name PATH).path


Nu for at ændre dette, fanger vi først den oprindelige sti, der skal ændres:


$oldpath = (Get-ItemProperty -Path ‘Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment’ -Name PATH).path


Nu definerer vi, hvad den nye vej skal se ud, i dette tilfælde tilføjer vi en ny mappe:


$newpath = “$oldpath;c:path	ofolder”


Bemærk: Sørg for, at $ newpath ser ud, hvordan du vil have det til at se ud, hvis ikke, så kan du beskadige dit operativsystem.


Anvend nu den nye værdi:


Set-ItemProperty -Path ‘Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetControlSession ManagerEnvironment’ -Name PATH -Value $newPath


Kontroller nu, at det ser ud til, hvordan du forventer det:


Get-ItemProperty -Path ‘Registry::HKEY\_LOCAL\_MACHINESystemCurrentControlSetContro
lSession ManagerEnvironment’ -Name PATH).Path


Du kan nu genstarte din powershell terminal (eller endda genstart maskinen) og se, at den ikke ruller tilbage til den gamle værdi igen. Bemærk, at rækkefølgen af ​​stierne kan ændres, så den er i alfabetisk rækkefølge, så sørg for at kontrollere hele linjen, for at gøre det nemmere, kan du dele output i rækker ved at bruge halvkolon som en delimeter:


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