Définition de la variable de chemin Windows PowerShell
J'ai découvert que la définition de la variable D'environnement PATH n'affecte que l'ancienne invite de commande. PowerShell semble avoir des paramètres d'environnement différents. Comment modifier les variables D'environnement pour PowerShell (v1)?
Remarque:
Je veux rendre mes modifications permanentes, donc je n'ai pas besoin de les définir chaque fois que je lance PowerShell. PowerShell a-t-il un fichier de profil? Quelque chose comme profil Bash sur Unix?
12 réponses
Changer les variables d'environnement réelles peut être fait par
utilisation des informations env: namespace / drive
. Par exemple, ce
le code mettra à jour la variable d'environnement path:
$env:Path = "SomeRandomPath";
Il existe des moyens de rendre les paramètres d'environnement permanents, mais si vous ne les utilisez que de PowerShell, c'est probablement beaucoup mieux utiliser votre profil pour lancer le paramètre. Au démarrage, PowerShell exécutera any . ps1 fichiers qu'il trouve dans le répertoire WindowsPowerShell sous Dossier Mes Documents. En général, vous avoir un profil . ps1 fichier déjà là. Le chemin sur mon ordinateur est
c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
Si, pendant une session PowerShell, vous devez modifiez temporairement la variable D'environnement PATH, vous pouvez faire de cette façon:
$env:Path += ";C:\Program Files\GnuWin32\bin"
Vous pouvez également modifier de façon permanente les variables d'environnement utilisateur/système (c'est-à-dire qu'elles seront persistantes entre les redémarrages du shell) avec
### 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:\bin", [EnvironmentVariableTarget]::Machine)
À partir de L'invite PowerShell:
setx PATH "$env:path;\the\directory\to\add" -m
Vous devriez alors voir le texte:
SUCCESS: Specified value was saved.
Redémarrez votre session, et la variable sera disponible. setx
peut également être utilisé pour définir des variables arbitraires. Tapez setx /?
à l'invite de documentation.
Avant de jouer avec votre chemin de cette façon, assurez-vous d'enregistrer une copie de votre chemin existant en faisant $env:path >> a.out
dans une invite PowerShell.
Bien que la réponse acceptée actuelle fonctionne dans le sens où la variable path est mise à jour en permanence à partir du contexte de PowerShell, elle ne met pas réellement à jour la variable d'environnement stockée dans le registre windows. Pour y parvenir, vous pouvez évidemment utiliser PowerShell aussi bien:
$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
Plus d'infos ici: http://blogs.technet.com/b/heyscriptingguy/archive/2011/07/23/use-powershell-to-modify-your-environmental-path.aspx
Si vous utilisez la communauté PowerShell extensions, la commande appropriée pour ajouter un chemin à la variable d'environnement path est:
Add-PathVariable "C:\NewFolderToAddToTheList" -Target Machine
Comme la réponse de JeanT , je voulais une abstraction autour de l'ajout au chemin. Contrairement à la réponse de JeanT, j'en avais besoin pour fonctionner sans interaction de l'utilisateur. Autre comportement que je cherchais:
- met à jour
$env:Path
de sorte que la modification prend effet dans la session en cours - persiste le changement de variable d'environnement pour les sessions futures
- n'ajoute pas de chemin en double lorsque le même chemin existe déjà
Dans le cas où c'est utile, le voici:
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 ';'
}
}
Vérifier mon essentiel pour la fonction Remove-EnvPath
correspondante.
Cela définit le chemin de la session en cours et invite l'utilisateur à l'ajouter définitivement:
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'
}
}
, Vous pouvez ajouter cette fonction à votre profil par défaut, (Microsoft.PowerShell_profile.ps1
), généralement situé à %USERPROFILE%\Documents\WindowsPowerShell
.
Toutes les réponses suggérant un changement permanent ont le même problème: elles cassent la valeur du registre path.
SetEnvironmentVariable
tourne la REG_EXPAND_SZ
valeur %SystemRoot%\system32
en REG_SZ
valeur de C:\Windows\system32
.
Toutes les autres variables du chemin sont également perdues. Ajouter de nouveaux en utilisant %myNewPath%
ne fonctionnera plus.
Voici un script Set-PathVariable.ps1
, que j'utilise pour résoudre ce problème:
[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
}
J'explique le problème plus en détail dans un blog.
Comme Jonathan Leaders mentionné ici, il est important d'exécuter la commande / script elevated pour pouvoir changer les variables d'environnement pour 'machine' , mais l'exécution de certaines commandes elevated ne doit pas être faite avec les Extensions de la communauté, donc j'aimerais modifier et étendre Jeant's réponse d'une certaine manière, cette modification des variables de la machine peut également être effectuée même si le script lui-même n'est pas exécuté surélevé:
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
}
}
La plupart des réponses ne s'adressent pas à UAC. Cela couvre les questions UAC.
Installez D'abord les Extensions de la communauté PowerShell: choco install pscx
via http://chocolatey.org/ (vous devrez peut-être redémarrer votre environnement shell).
Puis activez pscx
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #allows scripts to run from the interwebs, such as pcsx
Ensuite, utilisez Invoke-Elevated
Invoke-Elevated {Add-PathVariable $args[0] -Target Machine} -ArgumentList $MY_NEW_DIR
En S'appuyant sur la réponse de @ Michael Kropat, j'ai ajouté un paramètre pour ajouter le nouveau chemin à la variable PATH
existante et une vérification pour éviter l'ajout d'un chemin non existant:
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 ';'
}
}
}
}
MA SUGGESTION EST CELLE-CI j'ai testé cela pour ajouter C:\oracle\x64\bin Pour chemin en permanence et cela fonctionne bien.
$ENV:PATH
La première façon est simplement de faire:
$ENV:PATH=”$ENV:PATH;c:\path\to\folder”
Mais ce changement n'est pas permanent, $env:path reviendra par défaut à ce qu'il était avant dès que vous fermez votre terminal powershell et le rouvrez à nouveau. C'est parce que vous avez appliqué la modification au niveau de la session et non au niveau de la source (qui est le niveau du registre). Pour afficher la valeur globale de $env:chemin d'accès, faire:
Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH
, Ou, plus précisément:
(Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
Maintenant pour changer cela, nous avons d'abord capturer le chemin d'origine qui doit être modifié:
$oldpath = (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
Maintenant, nous définissons à quoi devrait ressembler le nouveau chemin, dans ce cas, nous ajoutons un nouveau dossier:
$newpath = “$oldpath;c:\path\to\folder”
Remarque: Assurez-vous que le $newpath ressemble à ce que vous voulez, sinon vous pourriez endommager votre système d'exploitation.
Maintenant, appliquez la nouvelle valeur:
Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH -Value $newPath
Maintenant, faites une dernière vérification qu'il ressemble à ce que vous attendez il:
Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Contro
l\Session Manager\Environment’ -Name PATH).Path
Vous pouvez maintenant redémarrer votre terminal powershell (ou même redémarrer la machine) et voir qu'il ne revient pas à son ancienne valeur. Notez que l'ordre des chemins peut changer de sorte qu'il soit dans l'ordre alphabétique, alors assurez-vous de vérifier toute la ligne, pour le rendre plus facile, vous pouvez diviser la sortie en lignes en utilisant le point-virgule comme un delimeter:
($env:path).split(“;”)