Existe-t-il une commande permettant d'actualiser les variables d'environnement à partir de l'invite de commande sous Windows?

StackOverflow https://stackoverflow.com/questions/171588

Question

Si je modifie ou ajoute une variable d'environnement, je dois redémarrer l'invite de commande. Existe-t-il une commande que je pourrais exécuter qui le ferait sans redémarrer CMD?

Était-ce utile?

La solution

Vous pouvez capturer les variables d'environnement système avec un script vbs, mais vous avez besoin d'un script bat pour modifier réellement les variables d'environnement actuelles. Il s'agit donc d'une solution combinée.

Créez un fichier nommé resetvars.vbs contenant ce code, puis enregistrez-le sur le chemin:

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("System")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
path = oEnv("PATH")

set oEnv=oShell.Environment("User")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next

path = path & ";" & oEnv("PATH")
oFile.WriteLine("SET PATH=" & path)
oFile.Close

créez un autre nom de fichier resetvars.bat contenant ce code, même emplacement:

@echo off
%~dp0resetvars.vbs
call "%TEMP%\resetvars.bat"

Lorsque vous souhaitez actualiser les variables d'environnement, exécutez simplement resetvars.bat

Apologetics :

Les deux principaux problèmes que je rencontrais avec cette solution étaient

a. , je ne trouvais pas de moyen simple d'exporter les variables d'environnement d'un script vbs vers l'invite de commande, et

b. la variable d'environnement PATH est une concaténation des variables utilisateur et système PATH.

Je ne sais pas quelle est la règle générale pour les variables en conflit entre l'utilisateur et le système. J'ai donc choisi de remplacer le système par l'utilisateur, sauf dans la variable PATH qui est gérée spécifiquement.

J'utilise le mécanisme bizarre vbs + bat + temporaire pour contourner le problème de l'exportation de variables à partir de vbs.

Remarque : ce script ne supprime pas les variables.

Cela peut probablement être amélioré.

ajouté

Si vous devez exporter l'environnement d'une fenêtre de commande à une autre, utilisez ce script (appelons-le exportvars.vbs):

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("Process")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
oFile.Close

Lancez <=> dans la fenêtre que vous souhaitez exporter à partir de , passez à la fenêtre que vous souhaitez exporter vers , puis tapez:

"%TEMP%\resetvars.bat"

Autres conseils

Voici ce que Chocolatey utilise.

https://github.com/ chocolatey / choco / blob / master / src / chocolatey.resources / redirections / RefreshEnv.cmd

@echo off
::
:: RefreshEnv.cmd
::
:: Batch file to read environment variables from registry and
:: set session variables to these values.
::
:: With this batch file, there should be no need to reload command
:: environment every time you want environment changes to propagate

echo | set /p dummy="Reading environment variables from registry. Please wait... "

goto main

:: Set one environment variable from registry key
:SetFromReg
    "%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > "%TEMP%\_envset.tmp" 2>NUL
    for /f "usebackq skip=2 tokens=2,*" %%A IN ("%TEMP%\_envset.tmp") do (
        echo/set %~3=%%B
    )
    goto :EOF

:: Get a list of environment variables from registry
:GetRegEnv
    "%WinDir%\System32\Reg" QUERY "%~1" > "%TEMP%\_envget.tmp"
    for /f "usebackq skip=2" %%A IN ("%TEMP%\_envget.tmp") do (
        if /I not "%%~A"=="Path" (
            call :SetFromReg "%~1" "%%~A" "%%~A"
        )
    )
    goto :EOF

:main
    echo/@echo off >"%TEMP%\_env.cmd"

    :: Slowly generating final file
    call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> "%TEMP%\_env.cmd"
    call :GetRegEnv "HKCU\Environment">>"%TEMP%\_env.cmd" >> "%TEMP%\_env.cmd"

    :: Special handling for PATH - mix both User and System
    call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> "%TEMP%\_env.cmd"
    call :SetFromReg "HKCU\Environment" Path Path_HKCU >> "%TEMP%\_env.cmd"

    :: Caution: do not insert space-chars before >> redirection sign
    echo/set Path=%%Path_HKLM%%;%%Path_HKCU%% >> "%TEMP%\_env.cmd"

    :: Cleanup
    del /f /q "%TEMP%\_envset.tmp" 2>nul
    del /f /q "%TEMP%\_envget.tmp" 2>nul

    :: Set these variables
    call "%TEMP%\_env.cmd"

    echo | set /p dummy="Done"
    echo .

De par sa conception, il n'existe pas de mécanisme intégré permettant à Windows de propager une variable d'environnement ajouter / modifier / supprimer à un cmd.exe déjà en cours d'exécution, à partir d'un autre cmd.exe ou de "Mon ordinateur - > Propriétés - & Gt; Paramètres avancés - & Gt; Variables d'environnement & ";

Si vous modifiez ou ajoutez une nouvelle variable d'environnement en dehors de la portée d'une invite de commande ouverte existante, vous devez soit redémarrer l'invite de commande, soit l'ajouter manuellement à l'aide de SET dans l'invite de commande existante.

Le La dernière réponse acceptée affiche une solution partielle en actualisant manuellement toutes les variables d'environnement d'un script. Le script gère le cas d'utilisation de la modification globale des variables d'environnement dans & "Mon ordinateur ... Variables d'environnement &"; Mais si une variable d'environnement est modifiée dans un cmd.exe, le script ne le transmettra pas à un autre. exécuter cmd.exe.

Sur Windows 7/8/10, vous pouvez installer Chocolatey avec un script pour cela.

Après avoir installé Chocolatey, tapez simplement & "; refreshenv &"; sans guillemets.

Ceci fonctionne sur Windows 7: SET PATH=%PATH%;C:\CmdShortcuts

testé en tapant echo% PATH% et cela a fonctionné, très bien. également défini si vous ouvrez une nouvelle cmd, nul besoin de ces redémarrages embêtants:)

Je suis tombé sur cette réponse avant de finalement trouver une solution plus facile.

Redémarrez simplement explorer.exe dans le gestionnaire de tâches.

Je n'ai pas testé, mais vous devrez peut-être aussi rouvrir votre invite de commande.

Nous remercions Timo Huovinen ici: Noeud non reconnu bien que installé avec succès (si cela vous a aidé, merci de donner crédit à cet homme pour le commentaire).

Utilisez " setx " et redémarrez l'invite de commande

Il existe un outil de ligne de commande nommé " setx " pour ce travail. Il s’agit des lectures et écritures des variables env. Les variables persistent après la fermeture de la fenêtre de commande.

It " Crée ou modifie des variables d’environnement dans l’environnement utilisateur ou système, sans programmation ni script. La commande setx récupère également les valeurs des clés de registre et les écrit les en fichiers texte. "

Remarque: les variables créées ou modifiées par cet outil seront disponibles dans les futures fenêtres de commande, mais pas dans la fenêtre de commande CMD.exe actuelle. Donc, vous devez redémarrer.

Si setx est manquant:

Ou modifiez le registre

MSDN indique:

  

Pour ajouter ou modifier par programme des variables d’environnement système, ajoutez   les au    HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session   Gestionnaire \ Environnement , puis diffusez une WM_SETTINGCHCH .   message avec lParam défini sur la chaîne & "; Environnement &";

     

Ceci permet aux applications, telles que le shell, de récupérer vos mises à jour.

L'appel de cette fonction a fonctionné pour moi:

VOID Win32ForceSettingsChange()
{
    DWORD dwReturnValue;
    ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
}

La meilleure méthode que j'ai proposée consistait simplement à interroger le registre. Voici mon exemple.

Dans mon exemple, j'ai effectué une installation à l'aide d'un fichier de commandes qui a ajouté de nouvelles variables d'environnement. J'avais besoin de faire les choses avec cela dès que l'installation était terminée, mais j'étais incapable de générer un nouveau processus avec ces nouvelles variables. J'ai testé la création d'une autre fenêtre d'explorateur et rappelé cmd.exe. Cela a fonctionné, mais sous Vista et Windows 7, Explorer ne fonctionne que comme une instance unique et normalement en tant que personne connectée. Cela échouerait avec l'automatisation, car j'avais besoin de mes comptes administrateur faire des choses indépendamment de l'exécution à partir du système local ou en tant qu'administrateur sur la boîte. La limitation à ceci est qu'il ne gère pas des choses comme le chemin, cela ne fonctionne que sur des variables d'environnement simples. Cela m'a permis d'utiliser un lot pour accéder à un répertoire (avec des espaces) et copier dans des fichiers tels que .exes, etc. Ceci a été écrit aujourd'hui à partir de ressources de mai sur stackoverflow.com

Appels par lots d'origine vers un nouveau lot:

testenvget.cmd SDROOT (ou quelle que soit la variable)

@ECHO OFF
setlocal ENABLEEXTENSIONS
set keyname=HKLM\System\CurrentControlSet\Control\Session Manager\Environment
set value=%1
SET ERRKEY=0

REG QUERY "%KEYNAME%" /v "%VALUE%" 2>NUL| FIND /I "%VALUE%"
IF %ERRORLEVEL% EQU 0 (
ECHO The Registry Key Exists 
) ELSE (
SET ERRKEY=1
Echo The Registry Key Does not Exist
)

Echo %ERRKEY%
IF %ERRKEY% EQU 1 GOTO :ERROR

FOR /F "tokens=1-7" %%A IN ('REG QUERY "%KEYNAME%" /v "%VALUE%" 2^>NUL^| FIND /I "%VALUE%"') DO (
ECHO %%A
ECHO %%B
ECHO %%C
ECHO %%D
ECHO %%E
ECHO %%F
ECHO %%G
SET ValueName=%%A
SET ValueType=%%B
SET C1=%%C
SET C2=%%D
SET C3=%%E
SET C4=%%F
SET C5=%%G
)

SET VALUE1=%C1% %C2% %C3% %C4% %C5%
echo The Value of %VALUE% is %C1% %C2% %C3% %C4% %C5%
cd /d "%VALUE1%"
pause
REM **RUN Extra Commands here**
GOTO :EOF

:ERROR
Echo The the Enviroment Variable does not exist.
pause
GOTO :EOF

En outre, il existe une autre méthode que j'ai proposée à partir de différentes idées. S'il vous plaît voir ci-dessous. Cela va essentiellement obtenir la variable de chemin la plus récente du registre, cependant, cela causera un certain nombre de problèmes car la requête de registre va donner des variables en elle-même, ce qui signifie que partout où il y a une variable, cela ne fonctionnera pas, donc pour lutter contre ce problème I fondamentalement, doublez le chemin. Très sale. La méthode la plus préférée serait de faire:     Définir le chemin =% chemin%; C: \ Program Files \ Software .... \

Indépendamment du nouveau fichier de commandes, soyez prudent.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
set org=%PATH%
for /f "tokens=2*" %%A in ('REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path ^|FIND /I "Path"') DO (
SET path=%%B
)
SET PATH=%org%;%PATH%
set path

Il est possible de le faire en écrasant la table d'environnement au sein même d'un processus spécifié.

Pour prouver le concept, j’ai écrit cet exemple d’application, qui vient de modifier une seule variable d’environnement (connue) dans un processus cmd.exe:

typedef DWORD (__stdcall *NtQueryInformationProcessPtr)(HANDLE, DWORD, PVOID, ULONG, PULONG);

int __cdecl main(int argc, char* argv[])
{
    HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
    NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtDll, "NtQueryInformationProcess");

    int processId = atoi(argv[1]);
    printf("Target PID: %u\n", processId);

    // open the process with read+write access
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 0, processId);
    if(hProcess == NULL)
    {
        printf("Error opening process (%u)\n", GetLastError());
        return 0;
    }

    // find the location of the PEB
    PROCESS_BASIC_INFORMATION pbi = {0};
    NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
    if(status != 0)
    {
        printf("Error ProcessBasicInformation (0x%8X)\n", status);
    }
    printf("PEB: %p\n", pbi.PebBaseAddress);

    // find the process parameters
    char *processParamsOffset = (char*)pbi.PebBaseAddress + 0x20; // hard coded offset for x64 apps
    char *processParameters = NULL;
    if(ReadProcessMemory(hProcess, processParamsOffset, &processParameters, sizeof(processParameters), NULL))
    {
        printf("UserProcessParameters: %p\n", processParameters);
    }
    else
    {
        printf("Error ReadProcessMemory (%u)\n", GetLastError());
    }

    // find the address to the environment table
    char *environmentOffset = processParameters + 0x80; // hard coded offset for x64 apps
    char *environment = NULL;
    ReadProcessMemory(hProcess, environmentOffset, &environment, sizeof(environment), NULL);
    printf("environment: %p\n", environment);

    // copy the environment table into our own memory for scanning
    wchar_t *localEnvBlock = new wchar_t[64*1024];
    ReadProcessMemory(hProcess, environment, localEnvBlock, sizeof(wchar_t)*64*1024, NULL);

    // find the variable to edit
    wchar_t *found = NULL;
    wchar_t *varOffset = localEnvBlock;
    while(varOffset < localEnvBlock + 64*1024)
    {
        if(varOffset[0] == '\0')
        {
            // we reached the end
            break;
        }
        if(wcsncmp(varOffset, L"ENVTEST=", 8) == 0)
        {
            found = varOffset;
            break;
        }
        varOffset += wcslen(varOffset)+1;
    }

    // check to see if we found one
    if(found)
    {
        size_t offset = (found - localEnvBlock) * sizeof(wchar_t);
        printf("Offset: %Iu\n", offset);

        // write a new version (if the size of the value changes then we have to rewrite the entire block)
        if(!WriteProcessMemory(hProcess, environment + offset, L"ENVTEST=def", 12*sizeof(wchar_t), NULL))
        {
            printf("Error WriteProcessMemory (%u)\n", GetLastError());
        }
    }

    // cleanup
    delete[] localEnvBlock;
    CloseHandle(hProcess);

    return 0;
}

Exemple de sortie:

>set ENVTEST=abc

>cppTest.exe 13796
Target PID: 13796
PEB: 000007FFFFFD3000
UserProcessParameters: 00000000004B2F30
environment: 000000000052E700
Offset: 1528

>set ENVTEST
ENVTEST=def

Notes

Cette approche serait également limitée aux restrictions de sécurité. Si la cible est exécutée à une altitude supérieure ou à un compte supérieur (tel que SYSTEM), nous ne serons pas autorisés à modifier sa mémoire.

Si vous vouliez faire cela sur une application 32 bits, les décalages codés en dur ci-dessus deviendraient 0x10 et 0x48 respectivement. Ces décalages peuvent être trouvés en vidant les structures _PEB et _RTL_USER_PROCESS_PARAMETERS dans un débogueur (par exemple, dans WinDbg dt _PEB et dt _RTL_USER_PROCESS_PARAMETERS)

Pour modifier la preuve de concept en ce dont le PO a besoin, il suffirait d’énumérer les variables d’environnement système et utilisateur actuelles (telles que documentées par la réponse de @ tsadok) et d’écrire la table d’environnement complète dans la mémoire du processus cible. .

Éditer: La taille du bloc d'environnement est également stockée dans la structure _RTL_USER_PROCESS_PARAMETERS, mais la mémoire est allouée sur le tas. Donc, d’un processus externe, nous n’aurions pas la possibilité de le redimensionner et de le rendre plus grand. J'ai joué avec l'utilisation de VirtualAllocEx pour allouer de la mémoire supplémentaire dans le processus cible pour le stockage de l'environnement et j'ai pu définir et lire une table entièrement nouvelle. Malheureusement, toute tentative de modification de l'environnement par rapport aux moyens normaux plantera et brûlera, car l'adresse ne pointe plus vers le tas (il se plantera dans RtlSizeHeap).

Les variables d'environnement sont conservées dans HKEY_LOCAL_MACHINE \ SYSTEM \ ControlSet \ Control \ Gestionnaire de sessions \ Environment.

La plupart des variables env utiles, telles que Path, sont stockées sous le nom REG_SZ. Il existe plusieurs moyens d’accéder au registre, y compris à REGEDIT:

REGEDIT /E &lt;filename&gt; "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"

La sortie commence par des nombres magiques. Donc, pour le rechercher avec la commande find, il doit être tapé et redirigé: type <filename> | findstr -c:\"Path\"

Ainsi, si vous souhaitez simplement actualiser la variable de chemin d'accès dans votre session de commande en cours avec le contenu des propriétés système, le script de traitement par lots suivant fonctionne correctement:

RefreshPath.cmd:

    @echo off

    REM This solution requests elevation in order to read from the registry.

    if exist %temp%\env.reg del %temp%\env.reg /q /f

    REGEDIT /E %temp%\env.reg "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"

    if not exist %temp%\env.reg (
       echo "Unable to write registry to temp location"
       exit 1
       )

    SETLOCAL EnableDelayedExpansion

    for /f "tokens=1,2* delims==" %%i in ('type %temp%\env.reg ^| findstr -c:\"Path\"=') do (
       set upath=%%~j
       echo !upath:\\=\! >%temp%\newpath
       )

     ENDLOCAL

     for /f "tokens=*" %%i in (%temp%\newpath) do set path=%%i

La confusion peut être qu'il existe quelques endroits pour démarrer la cmd. Dans mon cas, j'ai exécuté cmd à partir de l'explorateur Windows et les variables d'environnement n'ont pas changé lors du démarrage de cmd à partir de & "; Exécuter &"; (touche Windows + r) l'environnement a été modifié .

Dans mon cas, je devais arrêter le processus de l'explorateur Windows à partir du gestionnaire de tâches, puis le redémarrer à nouveau à partir du gestionnaire de tâches .

Une fois que j'ai fait cela, j'ai eu accès à la nouvelle variable d'environnement à partir d'une cmd créée à partir de l'explorateur Windows.

Essayez d’ouvrir une nouvelle invite de commande en tant qu’administrateur. Cela a fonctionné pour moi sous Windows 10. (Je sais que c'est une vieille réponse, mais je devais le partager car il est absurde d'écrire un script VBS, car c'est absurde).

Le moyen le plus simple d’ajouter une variable au chemin sans redémarrer la session en cours consiste à ouvrir l’invite de commande et à taper:

PATH=(VARIABLE);%path%

et appuyez sur entrez .

pour vérifier si votre variable est chargée, tapez

PATH

et appuyez sur entrez . Cependant, la variable ne fera partie du chemin que jusqu'au redémarrage.

Le redémarrage de l'explorateur l'a fait pour moi, mais uniquement pour les nouveaux terminaux cmd.

Le terminal sur lequel j'ai défini le chemin d'accès peut déjà voir la nouvelle variable Chemin (sous Windows 7).

taskkill /f /im explorer.exe && explorer.exe

J'utilise le code suivant dans mes scripts de lot:

if not defined MY_ENV_VAR (
    setx MY_ENV_VAR "VALUE" > nul
    set MY_ENV_VAR=VALUE
)
echo %MY_ENV_VAR%

En utilisant SET après SETX , il est possible d'utiliser le & "local &"; variable directement sans avoir à redémarrer la fenêtre de commande. Et lors de la prochaine exécution, la variable d’environnement sera utilisée.

redémarrez explorer.exe > > testé sur Win 8 X64

J'ai aimé l'approche suivie par Chocolatey, telle que publiée dans la réponse anonyme d'un lâche, car il s'agit d'une approche purement groupée. Cependant, il laisse un fichier temporaire et des variables temporaires qui traînent. J'ai créé une version plus propre pour moi-même.

Créez un fichier refreshEnv.bat quelque part sur votre PATH. Actualisez votre environnement de console en exécutant refreshEnv.

@ECHO OFF
REM Source found on https://github.com/DieterDePaepe/windows-scripts
REM Please share any improvements made!

REM Code inspired by http://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w

IF [%1]==[/?] GOTO :help
IF [%1]==[/help] GOTO :help
IF [%1]==[--help] GOTO :help
IF [%1]==[] GOTO :main

ECHO Unknown command: %1
EXIT /b 1 

:help
ECHO Refresh the environment variables in the console.
ECHO.
ECHO   refreshEnv       Refresh all environment variables.
ECHO   refreshEnv /?        Display this help.
GOTO :EOF

:main
REM Because the environment variables may refer to other variables, we need a 2-step approach.
REM One option is to use delayed variable evaluation, but this forces use of SETLOCAL and
REM may pose problems for files with an '!' in the name.
REM The option used here is to create a temporary batch file that will define all the variables.

REM Check to make sure we don't overwrite an actual file.
IF EXIST %TEMP%\__refreshEnvironment.bat (
  ECHO Environment refresh failed!
  ECHO.
  ECHO This script uses a temporary file "%TEMP%\__refreshEnvironment.bat", which already exists. The script was aborted in order to prevent accidental data loss. Delete this file to enable this script.
  EXIT /b 1
)

REM Read the system environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM Read the user environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM PATH is a special variable: it is automatically merged based on the values in the
REM system and user variables.
REM Read the PATH variable from the system and user environment variables.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH`) DO (
  ECHO SET PATH=%%K>>%TEMP%\__refreshEnvironment.bat
)
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment /v PATH`) DO (
  ECHO SET PATH=%%PATH%%;%%K>>%TEMP%\__refreshEnvironment.bat
)

REM Load the variable definitions from our temporary file.
CALL %TEMP%\__refreshEnvironment.bat

REM Clean up after ourselves.
DEL /Q %TEMP%\__refreshEnvironment.bat

ECHO Environment successfully refreshed.

S'il ne s'agit que d'un (ou de plusieurs) vars spécifiques que vous souhaitez modifier, je pense que le moyen le plus simple consiste à utiliser une solution de contournement : définissez-le simplement dans votre environnement ET dans votre session de console actuelle

  • Set mettra la var dans votre session en cours
  • SetX mettra la variable dans l'environnement, mais PAS dans votre session en cours

J'ai ce simple script batch pour changer mon Maven de Java7 à Java8 (les deux env. vars). Le dossier batch est dans ma CHEMIN afin que je puisse toujours appeler ' j8 'et dans ma console et dans l'environnement, ma version de JAVA_HOME var est modifiée:

j8.bat:

@echo off
set JAVA_HOME=%JAVA_HOME_8%
setx JAVA_HOME "%JAVA_HOME_8%"

Jusqu'à présent, je trouve que cela fonctionne mieux et plus facile. Vous voulez probablement que cela soit dans une commande, mais ce n’est tout simplement pas là dans Windows ...

Première installation de choco:

  • si vous utilisez cmd @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

  • si vous utilisez Powershell Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Ensuite, vous pouvez exécuter refreshenv. Cela fonctionne à la fois avec cmd et powershell.

Il n'y a pas de solution directe, comme l'a dit Kev. Dans la plupart des cas, il est plus simple de générer une autre boîte CMD. Plus gênant, les programmes en cours ne sont pas non plus au courant (même si l’IIRC peut émettre un message à surveiller pour être informé de ce changement).

La situation a été pire: dans les anciennes versions de Windows, vous deviez vous déconnecter, puis vous reconnecter pour prendre en compte les modifications ...

J'utilise ce script Powershell pour ajouter à la variable CHEMIN . Avec un petit ajustement, cela peut fonctionner dans votre cas aussi, je crois.

#REQUIRES -Version 3.0

if (-not ("win32.nativemethods" -as [type])) {
    # import sendmessagetimeout from win32
    add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
   IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
   uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}

$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero

function global:ADD-PATH
{
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)] 
        [string] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $null) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # Get the current search path from the environment keys in the registry.
    $oldPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # See if the new Folder is already in the path.
    if ($oldPath | Select-String -SimpleMatch $Folder){ 
        return 'Folder already within $ENV:PATH' 
    }

    # Set the New Path and add the ; in front
    $newPath=$oldPath+';'+$Folder
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show our results back to the world
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}

function global:REMOVE-PATH {
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)]
        [String] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $NULL) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # add a leading ";" if missing
    if ($Folder[0] -ne ";") {
        $Folder = ";" + $Folder;
    }

    # Get the Current Search Path from the environment keys in the registry
    $newPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # Find the value to remove, replace it with $NULL. If it's not found, nothing will change and you get a message.
    if ($newPath -match [regex]::Escape($Folder)) { 
        $newPath=$newPath -replace [regex]::Escape($Folder),$NULL 
    } else { 
        return "The folder you mentioned does not exist in the PATH environment" 
    }

    # Update the Environment Path
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show what we just did
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}


# Use ADD-PATH or REMOVE-PATH accordingly.

#Anything to Add?

#Anything to Remove?

REMOVE-PATH "%_installpath_bin%"

Merci d’avoir posté cette question, qui est très intéressante, même en 2019 (En effet, il n’est pas facile de renouveler le shell cmd car c’est une instance unique, comme mentionné ci-dessus), car le renouvellement des variables d’environnement dans windows permet de tâches d’automatisation sans avoir à redémarrer manuellement la ligne de commande.

Par exemple, nous l'utilisons pour autoriser le déploiement et la configuration de logiciels sur un grand nombre de machines que nous réinstallons régulièrement. Et je dois admettre qu’avoir à redémarrer la ligne de commande pendant le déploiement de notre logiciel serait très peu pratique et exigerait que nous trouvions des solutions de contournement qui ne sont pas nécessairement agréables. Passons à notre problème. Nous procédons comme suit.

1 - Nous avons un script batch qui appelle à son tour un script PowerShell comme celui-ci

[fichier: tâche.cmd] .

cmd > powershell.exe -executionpolicy unrestricted -File C:\path_here\refresh.ps1

2 - Ensuite, le script refresh.ps1 renouvelle les variables d'environnement à l'aide de clés de registre (GetValueNames (), etc.). Ensuite, dans le même script PowerShell, il suffit d’appeler les nouvelles variables d’environnement disponibles. Par exemple, dans un cas typique, si nous venons d'installer nodeJS auparavant avec cmd à l'aide de commandes silencieuses, une fois la fonction appelée, nous pouvons directement appeler npm pour installer, dans la même session, des packages particuliers, comme suit.

[fichier: refresh.ps1]

function Update-Environment {
    $locations = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session  Manager\Environment',
                 'HKCU:\Environment'
    $locations | ForEach-Object {
        $k = Get-Item $_
        $k.GetValueNames() | ForEach-Object {
            $name  = $_
            $value = $k.GetValue($_)

            if ($userLocation -and $name -ieq 'PATH') {
                $env:Path += ";$value"
            } else {

                Set-Item -Path Env:\$name -Value $value
            }
        }
        $userLocation = $true
    }
}
Update-Environment
#Here we can use newly added environment variables like for example npm install.. 
npm install -g create-react-app serve

Une fois le script PowerShell terminé, le script cmd continue avec d'autres tâches. Il ne faut pas oublier que, une fois la tâche terminée, cmd n'a toujours pas accès aux nouvelles variables d'environnement, même si le script powershell a mis à jour celles-ci dans sa propre session. C’est pourquoi nous effectuons toutes les tâches nécessaires dans le script powershell, qui peut appeler les mêmes commandes que cmd bien sûr.

non, je ne pense pas ... vous pouvez les régler manuellement. Donc, vous pouvez les mettre dans un fichier de commandes ou quelque chose.

pourrait probablement créer un utilitaire / script (si quelqu'un ne l'a pas déjà fait) qui interroge le registre et définit l'environnement actuel comme étant le même

Modifier: cela ne fonctionne que si les modifications de l'environnement que vous apportez résultent de l'exécution d'un fichier de commandes.

Si un fichier de traitement de commandes commence par SETLOCAL, il sera toujours rétabli dans votre environnement d'origine à la sortie, même si vous oubliez d'appeler ENDLOCAL avant la fin du traitement ou s'il se produit inopinément.

Presque tous les fichiers de commandes que j'écris commencent par <=> car dans la plupart des cas, je ne souhaite pas que les effets secondaires des modifications de l'environnement persistent. Dans les cas où je souhaite que certaines modifications de la variable d'environnement se propagent en dehors du fichier de commandes, mon dernier <=> se présente comme suit:

ENDLOCAL & (
  SET RESULT1=%RESULT1%
  SET RESULT2=%RESULT2%
)

Pour résoudre ce problème, j'ai modifié la variable d'environnement à l'aide de BOTH setx et set, puis j'ai redémarré toutes les instances de explorer.exe. Ainsi, tout processus démarré par la suite aura la nouvelle variable d’environnement.

Mon script de lot pour le faire:

setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"

taskkill /f /IM explorer.exe
start explorer.exe >nul
exit

Le problème avec cette approche est que toutes les fenêtres d’explorateur actuellement ouvertes seront fermées, ce qui est probablement une mauvaise idée - mais voyez le message de Kev pour savoir pourquoi cela est nécessaire

Ou vous pouvez simplement le faire manuellement via

  

Pour afficher ou modifier les variables d'environnement: Cliquez avec le bouton droit de la souris sur Poste de travail, puis sur   puis cliquez sur Propriétés. Cliquez sur l'onglet Avancé. Cliquez sur l'environnement   variables. Cliquez sur l'une des options suivantes, pour un utilisateur ou un utilisateur.   variable système: cliquez sur Nouveau pour ajouter un nouveau nom et une nouvelle valeur à la variable. Cliquez sur   une variable existante, puis cliquez sur Modifier pour changer son nom ou sa valeur.   Cliquez sur une variable existante, puis sur Supprimer pour la supprimer.    http://support.microsoft.com/kb/310519

Variables d'environnement Windows XP

%ALLUSERSPROFILE% (%PROGRAMDATA%)   C:\Documents and Settings\All Users
%APPDATA%   C:\Documents and Settings\{username}\Application Data
%COMPUTERNAME%  {computername}
%COMMONPROGRAMFILES%    C:\Program Files\Common Files
%COMMONPROGRAMFILES(x86)%   C:\Program Files (x86)\Common Files
%COMSPEC%   C:\Windows\System32\cmd.exe
%HOMEDRIVE% C:
%HOMEPATH%  \Documents and Settings\{username}
%LOCALAPPDATA%  Not available
%LOGONSERVER%   \\{domain_logon_server}
%PATH%  C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}
%PATHEXT%   .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.WSF;.WSH
%PROGRAMFILES%  C:\Program Files
%PROGRAMFILES(X86)% C:\Program Files (x86) (only in 64-bit version)
%PROMPT%    Code for current command prompt format. Code is usually $P$G
%SystemDrive%   C:
%SystemRoot%    The Windows directory, usually C:\Windows, formerly C:\WINNT
%TEMP% and %TMP%    C:\Documents and Settings\{username}\Local Settings\Temp
%USERDOMAIN%    {userdomain}
%USERNAME%  {username}
%USERPROFILE%   C:\Documents and Settings\{username}
%WINDIR%    C:\Windows
%PUBLIC%    
%PROGRAMDATA%   Only available in Windows Vista and newer versions
%PSModulePath%  

Variables d'environnement Windows 7

%ALLUSERSPROFILE% (%PROGRAMDATA%)   C:\ProgramData
%APPDATA%   C:\Users\{username}\AppData\Roaming
%COMPUTERNAME%  {computername}
%COMMONPROGRAMFILES%    C:\Program Files\Common Files
%COMMONPROGRAMFILES(x86)%   C:\Program Files (x86)\Common Files
%COMSPEC%   C:\Windows\System32\cmd.exe
%HOMEDRIVE% C:
%HOMEPATH%  \Users\{username}
%LOCALAPPDATA%  C:\Users\{username}\AppData\Local
%LOGONSERVER%   \\{domain_logon_server}
%PATH%  C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}
%PATHEXT%   .com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.msc
%PROGRAMFILES%  C:\Program Files
%PROGRAMFILES(X86)% C:\Program Files (x86) (only in 64-bit version)
%PROMPT%    Code for current command prompt format. Code is usually $P$G
%SystemDrive%   C:
%SystemRoot%    C:\Windows
%TEMP% and %TMP%    C:\Users\{username}\AppData\Local\Temp
%USERDOMAIN%    {userdomain}
%USERNAME%  {username}
%USERPROFILE%   C:\Users\{username}
%WINDIR%    C:\Windows
%PUBLIC%    C:\Users\Public
%PROGRAMDATA%   C:\ProgramData
%PSModulePath%  %SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\

http://www.binbert.com/blog/2010/09/default-environment-variable-values-of-windows-7-xp/

espérons que cela aide.

Il suffit de taper " # -r " (sans guillemets # avec l'option -r) dans votre terminal. Et vous êtes tous ensemble sur les chemins par défaut:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top