web-dev-qa-db-fra.com

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

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

432
Eric Schoonover

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, au même endroit:

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

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


Apologétique :

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

a. Je ne pouvais pas trouver un 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 étrange vbs + bat + bat temporaire pour contourner le problème de l'exportation de variables à partir de vbs.

Note: ce script ne supprime pas les variables.

Cela peut probablement être amélioré.

AJOUTÉ

Si vous avez besoin d'exporter l'environnement d'une fenêtre cmd à 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

Exécutez exportvars.vbs dans la fenêtre que vous souhaitez exporter from, puis passez à la fenêtre que vous souhaitez exporter to et tapez:

"%TEMP%\resetvars.bat"
130
itsadok

Voici ce que Chocolatey utilise.

https://github.com/chocolatey/choco/blob/master/src/chocolatey.resources/redirects/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 .
94
anonymous coward

De par sa conception, il n’existe pas de mécanisme intégré permettant à Windows de propager une variable d’environnement add/change/remove à un cmd.exe en cours d’exécution, un autre cmd.exe ou à partir de "Poste de travail -> Propriétés -> Paramètres avancés -> 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 dernière réponse acceptée montre 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 "Poste de travail ... Variables d'environnement", mais si une variable d'environnement est modifiée dans un cmd.exe, le script ne le propagera pas à un autre cmd.exe en cours d'exécution.

56
Kev

Sur Windows 7/8/10, vous pouvez installer Chocolatey qui a un script pour cela intégré.

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

55
jolly

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 commande Invite.

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

36
wharding28

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

testé en tapant echo% PATH% et cela a fonctionné, très bien. définissez également si vous ouvrez une nouvelle cmd, inutile de redémarrer ces satanés :)

32
kristofer månsson

Utilisez "setx" et redémarrez cmd Prompt

Il existe un outil de ligne de commande nommé " setx " pour ce travail. C'est pour lire et écrire variables env. Les variables persistent après la fermeture de la fenêtre de commande.

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

Remarque: les variables créées ou modifiées par cet outil seront disponibles dans les fenêtres de commande futures, 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 dit:

Pour ajouter ou modifier par programme des variables d’environnement système, ajoutez-les à la clé de Registre HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment , puis diffusez une WM_SETTINGCHANGE message avec lParam défini sur la chaîne " Environnement ".

Cela permet aux applications, telles que Shell, de récupérer vos mises à jour.

25
Jens A. Koch

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);
}
14
Brian Weed

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 batch ajoutant de nouvelles variables d'environnement. Je devais faire des choses avec cela dès que l'installation était terminée, mais je ne pouvais pas créer de nouveau processus avec ces nouvelles variables. J'ai testé la création d'une autre fenêtre d'Explorer et rappelé cmd.exe. Cela fonctionnait, mais sous Vista et Windows 7, l'Explorateur 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 administrateurs 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 me permettait d'utiliser un lot pour accéder à un répertoire (avec des espaces) et copier dans des fichiers tels que .exes, etc.

Appels de lot originaux 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 obtiendra essentiellement la variable de chemin la plus récente du registre; toutefois, 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. 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
11
Christopher Holmes

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

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

Remarques

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 seraient modifiés en 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 changer 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 l'intégralité de la table d'environnement dans la mémoire du processus cible.

Edit: 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 toute nouvelle table. 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 (elle se plantera dans RtlSizeHeap).

7
josh poley

Les variables d'environnement sont conservées dans HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment.

La plupart des variables env utiles, telles que Path, sont stockées sous le nom REG_SZ. Il y a plusieurs façons d'accéder au registre, y compris REGEDIT:

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

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

Par conséquent, 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 Cette solution demande une élévation pour pouvoir être lue dans le registre. 
 
 s'il existe% temp%\env.reg del% temp%\env.reg/q /f

 REGEDIT/E% temp%\env.reg "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001 \" Control\Session Manager\Environment "
 
 S'il n'existe pas% temp%\env.reg (
 Echo" Impossible d'écrire le registre dans l'emplacement temporaire "
 Exit 1 
) 
 
 SETLOCAL EnableDelayedExpansion 
 
 Pour/f "jetons = 1,2 * delims ==" %% i in ('type% temp%\env.reg ^ | findstr -c:\"Path \" = ') do (
 configurer upath = %% ~ j 
 echo! upath: \\ = \!>% temp%\newpath 
) 
 
 ENDLOCAL 
 
 pour/f "tokens = *" %% i in (% temp%\newpath) est-ce que set path = %% i
6
Algonaut

La confusion peut être qu'il existe quelques endroits pour démarrer le cmd. Dans mon cas, j'ai exécuté cmd à partir de Windows Explorer et l'environnement les variables n'ont pas changé au démarrage cmd à partir de "run" (touche Windows + r) l'environnement les variables ont été changées.

Dans mon cas, je devais simplement tuer le processus Windows Explorer 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 Windows Explorer.

5
Daniel Fensterheim

Redémarrer Explorer a fait cela pour moi, mais uniquement pour les nouveaux terminaux cmd.

Le terminal que j'ai défini le chemin pourrait déjà voir la nouvelle variable Chemin (sous Windows 7).

taskkill /f /im Explorer.exe && Explorer.exe
4
Vince

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

PATH=(VARIABLE);%path%

et appuyez sur enter.

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

PATH

et appuyez sur enter. Cependant, la variable ne sera qu'une partie du chemin jusqu'à ce que vous redémarriez.

4
Richard Woodruff

Essayez d'ouvrir une nouvelle commande en tant qu'administrateur. Cela a fonctionné pour moi sur 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 uniquement pour cela).

4
estebro

il suffit de redémarrer Explorer.exe >> testé sur Win 8 X64

3
SkyW3lker

J'utilise le code suivant dans mes scripts batch:

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 directement la variable "locale" sans avoir à redémarrer la fenêtre de commande. Et lors de la prochaine exécution, la variable d’environnement sera utilisée.

3
Sebastian

J'ai aimé l'approche suivie par Chocolatey, telle que publiée dans la réponse anonyme de lâche, car il s'agit d'une approche par lots. Cependant, il laisse un fichier temporaire et des variables temporaires qui traînent. J'ai fait 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.
3
DieterDP

D'abord installer 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.

2
Vasantha Ganesh K

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 est un solution de contournement: vient d'être défini dans votre environnement ET dans votre session de console actuelle.

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

J'ai ce simple script batch pour changer mon Maven de Java7 à Java8 (qui sont tous les deux env. Vars). Le dossier batch est dans mon CHEMIN var afin que je puisse toujours appeler 'j8' et dans ma console et dans l'environnement, ma variable Java_HOME 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 ...

2

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 la cmd Shell étant donné qu’il s’agit d’une instance unique, comme mentionné ci-dessus), car le renouvellement des variables d’environnement dans Windows permet d’effectuer de nombreuses tâches d’automatisation sans avoir à redémarrer manuellement la ligne de commande.

Par exemple, nous utilisons cela pour permettre au logiciel d'être déployé et configuré 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.

1
Andy McRae

Comme l'a dit Kev, il n'y a pas de solution directe. Dans la plupart des cas, il est plus simple de générer une autre boîte CMD. Plus ennuyeux, 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 était pire: dans les anciennes versions de Windows, vous deviez vous déconnecter, puis vous reconnecter pour prendre en compte les modifications ...

1
PhiLho

Si vous devez simplement actualiser les variables d’environnement dans Windows, exécutez refreshenv à partir de votre terminal plutôt que de redémarrer le PC.

1
Jasper

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%"
1
Iulian Dita

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

0
Keith Nicholas

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

Si un fichier 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 fermeture du lot ou s'il échoue de manière inattendue.

Presque tous les fichiers de commandes que j’écris commencent par SETLOCAL car, dans la plupart des cas, je ne souhaite pas que les effets secondaires des modifications de l’environnement soient conservés. Dans les cas où je souhaite que certaines modifications de la variable d'environnement se propagent en dehors du fichier de commandes, mon dernier ENDLOCAL ressemble à ceci:

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