it-swarm.com.de

Gibt es einen Befehl zum Aktualisieren von Umgebungsvariablen über den Befehl Eingabeaufforderung in Windows?

Wenn ich eine Umgebungsvariable ändere oder hinzufüge, muss ich den Befehl Eingabeaufforderung neu starten. Gibt es einen Befehl, den ich ausführen könnte, ohne CMD neu zu starten?

432
Eric Schoonover

Sie können die Systemumgebungsvariablen mit einem vbs-Skript erfassen, aber Sie benötigen ein bat-Skript, um die aktuellen Umgebungsvariablen tatsächlich zu ändern. Dies ist also eine kombinierte Lösung.

Erstellen Sie eine Datei mit dem Namen resetvars.vbs, die diesen Code enthält, und speichern Sie sie unter folgendem Pfad:

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

erstellen Sie einen anderen Dateinamen, resetvars.bat, der diesen Code enthält, denselben Speicherort:

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

Wenn Sie die Umgebungsvariablen aktualisieren möchten, führen Sie einfach resetvars.bat aus.


Apologetik :

Die zwei Hauptprobleme, die ich mit dieser Lösung hatte, waren

a. Ich konnte keine einfache Möglichkeit finden, Umgebungsvariablen aus einem vbs-Skript zurück in den Befehl Eingabeaufforderung zu exportieren, und

b. Die Umgebungsvariable PATH ist eine Verkettung der PATH-Variablen des Benutzers und des Systems.

Ich bin mir nicht sicher, wie die allgemeine Regel für widersprüchliche Variablen zwischen Benutzer und System lautet, und habe mich daher dafür entschieden, das Benutzer-Override-System zu verwenden, mit Ausnahme der PATH-Variablen, die speziell behandelt wird.

Ich benutze den seltsamen Mechanismus vbs + bat + temporary bat, um das Problem des Exportierens von Variablen aus vbs zu umgehen.

Anmerkung: Dieses Skript löscht keine Variablen.

Dies kann wahrscheinlich verbessert werden.

HINZUGEFÜGT

Wenn Sie die Umgebung von einem Cmd-Fenster in ein anderes exportieren müssen, verwenden Sie dieses Skript (nennen wir es 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

Führen Sie exportvars.vbs in dem Fenster aus, das Sie exportieren möchten von, wechseln Sie dann zu dem Fenster, das Sie exportieren möchten nach, und geben Sie Folgendes ein:

"%TEMP%\resetvars.bat"
130
itsadok

Hier ist, was Chocolatey verwendet.

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

In Windows ist kein integrierter Mechanismus zur Weitergabe einer Umgebungsvariablen add/change/remove an eine bereits ausgeführte cmd.exe von vorhanden eine andere cmd.exe oder von "Arbeitsplatz -> Eigenschaften -> Erweiterte Einstellungen -> Umgebungsvariablen".

Wenn Sie eine neue Umgebungsvariable außerhalb des Bereichs einer vorhandenen Eingabeaufforderung ändern oder hinzufügen, müssen Sie entweder die Eingabeaufforderung neu starten oder manuell mit SET in die vorhandene Eingabeaufforderung einfügen.

Die letzte akzeptierte Antwort zeigt eine teilweise Umgehung durch manuelles Aktualisieren aller Umgebungsvariablen in einem Skript. Das Skript behandelt den Anwendungsfall des globalen Änderns von Umgebungsvariablen in "Arbeitsplatz ... Umgebungsvariablen". Wenn jedoch eine Umgebungsvariable in einer cmd.exe geändert wird, gibt das Skript sie nicht an eine andere ausgeführte cmd.exe weiter.

56
Kev

Unter Windows 7/8/10 können Sie Chocolatey installieren, für das ein Skript eingebaut ist.

Geben Sie nach der Installation von Chocolatey einfach "refreshenv" ohne Anführungszeichen ein.

55
jolly

Ich bin auf diese Antwort gestoßen, bevor ich irgendwann eine einfachere Lösung gefunden habe.

Starten Sie einfach Explorer.exe im Task-Manager neu.

Ich habe nicht getestet, aber möglicherweise müssen Sie die Eingabeaufforderung erneut öffnen.

Gutschrift an Timo Huovinen hier: Knoten nicht erkannt, obwohl erfolgreich installiert (Wenn dies Ihnen geholfen hat, geben Sie diesem Mann bitte die Gutschrift für Kommentare).

36
wharding28

Dies funktioniert unter Windows 7: SET PATH=%PATH%;C:\CmdShortcuts

getestet durch Eingabe von echo% PATH% und es hat funktioniert, in Ordnung. setze auch, wenn du ein neues cmd öffnest, keine Notwendigkeit für diese lästigen Neustarts mehr :)

32

Benutze "setx" und starte cmd Prompt neu

Für diesen Job gibt es ein Befehlszeilentool mit dem Namen " setx ". Es dient zum Lesen und Schreiben von Umgebungsvariablen. Die Variablen bleiben bestehen, nachdem das Befehlsfenster geschlossen wurde.

Es "Erstellt oder ändert Umgebungsvariablen in der Benutzer- oder Systemumgebung, ohne dass Programmierung oder Skripterstellung erforderlich sind. Mit dem Befehl setx werden auch die Werte von Registrierungsschlüsseln abgerufen und in Textdateien geschrieben."

Hinweis: Mit diesem Tool erstellte oder geänderte Variablen sind in zukünftigen Befehlsfenstern verfügbar, jedoch nicht im aktuellen CMD.exe-Befehlsfenster. Sie müssen also neu starten.

Wenn setx fehlt:


Oder ändern Sie die Registrierung

MSDN sagt:

Um Systemumgebungsvariablen programmgesteuert hinzuzufügen oder zu ändern, fügen Sie sie dem Registrierungsschlüssel HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment hinzu, und senden Sie dann einen Broadcast WM_SETTINGCHANGE Nachricht mit lParam als Zeichenfolge " Umgebung ".

Auf diese Weise können Anwendungen wie die Shell Ihre Aktualisierungen abrufen.

25
Jens A. Koch

Das Aufrufen dieser Funktion hat bei mir funktioniert:

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

Die beste Methode, die ich mir ausgedacht habe, war einfach eine Registrierungsabfrage durchzuführen. Hier ist mein Beispiel.

In meinem Beispiel habe ich eine Installation mit einer Batch-Datei durchgeführt, in der neue Umgebungsvariablen hinzugefügt wurden. Ich musste dies tun, sobald die Installation abgeschlossen war, konnte aber keinen neuen Prozess mit diesen neuen Variablen erzeugen. Ich habe getestet, wie ich ein anderes Explorer-Fenster erzeugt habe, und habe cmd.exe aufgerufen. Dies hat funktioniert, aber unter Vista und Windows 7 wird der Explorer nur als einzelne Instanz und normalerweise als angemeldete Person ausgeführt Dinge tun, unabhängig davon, ob sie vom lokalen System oder als Administrator auf der Box ausgeführt werden. Die Einschränkung ist, dass es keine Dinge wie Pfad behandelt, dies funktionierte nur bei einfachen Umgebungsvariablen. Dies erlaubte mir, einen Stapel zu verwenden, um in ein Verzeichnis (mit Leerzeichen) zu gelangen und in Dateien zu kopieren, die .exes und so weiter ausführen

Orginal Batch-Aufrufe zu neuem Batch:

testenvget.cmd SDROOT (oder was auch immer die Variable ist)

@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

Es gibt auch eine andere Methode, die ich mir aus verschiedenen Ideen ausgedacht habe. Siehe unten. Grundsätzlich wird die neueste Pfadvariable aus der Registrierung abgerufen. Dies führt jedoch zu einer Reihe von Problemen, da die Registrierungsabfrage selbst Variablen enthält. Dies bedeutet, dass überall eine Variable vorhanden ist, die nicht funktioniert im Grunde verdoppeln Sie den Weg. Sehr böse. Die am besten geeignete Methode wäre: Setze Pfad =% Pfad%; C:\Programme\Software .... \

Unabhängig davon, ob es sich um die neue Batch-Datei handelt, gehen Sie bitte vorsichtig vor.

@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

Dies ist möglich, indem die Umgebungstabelle innerhalb eines bestimmten Prozesses selbst überschrieben wird.

Als Proof of Concept habe ich diese Beispiel-App geschrieben, die gerade eine einzelne (bekannte) Umgebungsvariable in einem cmd.exe-Prozess bearbeitet hat:

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

Beispielausgabe:

>set ENVTEST=abc

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

>set ENVTEST
ENVTEST=def

Anmerkungen

Dieser Ansatz würde sich auch auf Sicherheitsbeschränkungen beschränken. Wenn das Ziel auf einer höheren Ebene oder mit einem höheren Konto (z. B. SYSTEM) ausgeführt wird, haben wir keine Berechtigung, seinen Speicher zu bearbeiten.

Wenn Sie dies für eine 32-Bit-App tun möchten, werden die oben angegebenen fest codierten Offsets in 0x10 bzw. 0x48 geändert. Diese Offsets können durch Ausgeben der Strukturen _PEB und _RTL_USER_PROCESS_PARAMETERS in einem Debugger ermittelt werden (z. B. in WinDbg dt _PEB und dt _RTL_USER_PROCESS_PARAMETERS).

Um den Proof-of-Concept in das zu ändern, was das OP benötigt, werden lediglich die aktuellen System- und Benutzerumgebungsvariablen (wie in der Antwort von @ tsadok dokumentiert) aufgelistet und die gesamte Umgebungstabelle in den Speicher des Zielprozesses geschrieben.

Edit: Die Größe des Umgebungsblocks wird ebenfalls in der _RTL_USER_PROCESS_PARAMETERS-Struktur gespeichert, der Speicher wird jedoch auf dem Heap des Prozesses zugewiesen. Von einem externen Prozess aus hätten wir also nicht die Möglichkeit, die Größe zu ändern und sie zu vergrößern. Ich habe mit VirtualAllocEx herumgespielt, um zusätzlichen Speicher im Zielprozess für den Umgebungsspeicher zuzuweisen, und konnte eine völlig neue Tabelle festlegen und lesen. Leider wird jeder Versuch, die Umgebung von normalen Mitteln zu verändern, abstürzen und brennen, da die Adresse nicht mehr auf den Heap verweist (es wird in RtlSizeHeap abstürzen).

7
josh poley

Umgebungsvariablen werden in HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment gespeichert.

Viele der nützlichen Umgebungsvariablen, wie z. B. Path, werden als REG_SZ gespeichert. Es gibt verschiedene Möglichkeiten, auf die Registrierung zuzugreifen, einschließlich REGEDIT:

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

Die Ausgabe beginnt mit magischen Zahlen. Um es mit dem Befehl find zu durchsuchen, muss es eingegeben und umgeleitet werden: type <filename> | findstr -c:\"Path\"

Wenn Sie also nur die Pfadvariable in Ihrer aktuellen Befehlssitzung mit den Systemeigenschaften aktualisieren möchten, funktioniert das folgende Stapelskript einwandfrei:

RefreshPath.cmd:

 
 @echo off 
 
 REM Diese Lösung fordert eine Erhöhung an, um aus der Registrierung zu lesen. 
 
 falls vorhanden% temp%\env.reg del% temp%\env.reg/q /f[.____.[.____] REGEDIT/E% temp%\env.reg "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment "
 
 Falls nicht vorhanden% temp%\env.reg (
 Echo" Registrierung kann nicht in temporären Speicherort geschrieben werden "
 Exit 1 
) 
 
 SETLOCAL EnableDelayedExpansion 
 
 Für/f "Tokens = 1,2 * delims ==" %% i in ('type% temp%\env.reg ^ | findstr -c:\"Path \" = ') do (
 set upath = %% ~ j 
 echo! upath: \\ = \!>% temp%\newpath 
) 
 
 ENDLOCAL 
 
 für/f "tokens = *" %% i in (% temp%\newpath) setze Pfad = %% i
6
Algonaut

Das Verwirrende könnte sein, dass es einige Stellen gibt, an denen der Befehl beginnen kann. In meinem Fall habe ich cmd vom Windows Explorer und die Umgebung Variablen haben sich nicht geändert beim Starten cmd vom "Ausführen" (Windows-Taste +) ausgeführt r) die Umgebung Variablen wurden geändert.

In meinem Fall musste ich nur den Windows Explorer-Prozess über den Task-Manager beenden und dann über den Task-Manager erneut starten.

Sobald ich dies getan hatte, hatte ich Zugriff auf die neue Umgebungsvariable von einem cmd, der vom Windows Explorer erzeugt wurde.

5

Der Neustart des Explorers hat dies für mich getan, aber nur für neue cmd-Terminals.

Das Terminal, für das ich den Pfad festgelegt habe, konnte die neue Pfadvariable bereits sehen (in Windows 7).

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

Der einfachste Weg, dem Pfad eine Variable hinzuzufügen, ohne für die aktuelle Sitzung neu zu starten, besteht darin, den Befehl Eingabeaufforderung zu öffnen und Folgendes einzugeben:

PATH=(VARIABLE);%path%

und drücke enter.

um zu überprüfen, ob Ihre Variable geladen ist, geben Sie Folgendes ein

PATH

und drücke enter. Die Variable ist jedoch nur ein Teil des Pfads, bis Sie einen Neustart durchführen.

4

Versuchen Sie, als Administrator eine neue Eingabeaufforderung zu öffnen. Dies funktionierte für mich unter Windows 10. (Ich weiß, dass dies eine alte Antwort ist, aber ich musste dies teilen, weil es absurd ist, nur dafür ein VBS-Skript schreiben zu müssen).

4
estebro

starten Sie einfach Explorer.exe neu >> getestet auf Win 8 X64

3
SkyW3lker

Ich verwende den folgenden Code in meinen Batch-Skripten:

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

Durch Verwendung von SET nach SETX ist es möglich, die "lokale" Variable direkt zu verwenden, ohne das Befehlsfenster neu zu starten. Und beim nächsten Durchlauf wird die Umgebungsvariable verwendet.

3
Sebastian

Ich mochte den Ansatz von chocolatey, wie in der Antwort eines anonymen Feiglings angegeben, da es sich um einen reinen Batch-Ansatz handelt. Es verbleibt jedoch eine temporäre Datei und einige temporäre Variablen. Ich habe eine sauberere Version für mich gemacht.

Erstellen Sie eine Datei refreshEnv.bat irgendwo auf Ihrem PATH. Aktualisieren Sie Ihre Konsolenumgebung, indem Sie refreshEnv ausführen.

@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

Zuerst installiere choco:

  • bei Verwendung von 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"

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

Dann können Sie refreshenv ausführen. Es funktioniert sowohl mit Cmd als auch mit Powershell.

2

Wenn es sich nur um eine (oder einige) bestimmte Version handelt, die Sie ändern möchten, ist meiner Meinung nach der einfachste Weg ein Workaround: Einfach in Ihre Umgebung UND in Ihre aktuelle Konsolensitzung einfügen

  • Set setzt die Variable in Ihre aktuelle Sitzung
  • SetX legt die Variable in der Umgebung ab, jedoch NICHT in Ihrer aktuellen Sitzung

Ich habe dieses einfache Batch-Skript, um meinen Maven von Java7 auf Java8 zu ändern (beides env. Vars). Der Batch-Ordner befindet sich in meinem PFAD var so kann ich immer 'j8' aufrufen und in meiner Konsole und in der Umgebung wird mein Java_HOME var geändert:

j8.bat:

@echo off
set Java_HOME=%Java_HOME_8%
setx Java_HOME "%Java_HOME_8%"

Bis jetzt finde ich das am besten und einfachsten. Sie möchten wahrscheinlich, dass dies in einem Befehl geschieht, aber in Windows ist es einfach nicht vorhanden ...

2

Vielen Dank, dass Sie diese Frage gestellt haben, die selbst im Jahr 2019 sehr interessant ist (es ist in der Tat nicht einfach, den Shell-Cmd zu erneuern, da es sich um eine einzelne Instanz handelt, wie oben erwähnt), da durch das Erneuern von Umgebungsvariablen in Windows viele Automatisierungsaufgaben ausgeführt werden können, ohne dass dies erforderlich ist müssen Sie die Befehlszeile manuell neu starten.

Wir verwenden dies beispielsweise, um die Bereitstellung und Konfiguration von Software auf einer großen Anzahl von Computern zu ermöglichen, die wir regelmäßig neu installieren. Und ich muss zugeben, dass es sehr unpraktisch wäre, die Befehlszeile während der Bereitstellung unserer Software neu zu starten, und dass wir Problemumgehungen finden müssten, die nicht unbedingt angenehm sind. Kommen wir zu unserem Problem. Wir gehen wie folgt vor.

1 - Wir haben ein Batch-Skript, das wiederum ein Powershell-Skript wie dieses aufruft

[file: task.cmd].

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

2 - Danach erneuert das Skript refresh.ps1 die Umgebungsvariablen mithilfe von Registrierungsschlüsseln (GetValueNames () usw.). Dann müssen wir im selben Powershell-Skript nur die neuen verfügbaren Umgebungsvariablen aufrufen. In einem typischen Fall können wir beispielsweise, wenn wir NodeJS zuvor mit cmd mithilfe von unbeaufsichtigten Befehlen installiert haben, nach dem Aufruf der Funktion direkt npm aufrufen, um in derselben Sitzung bestimmte Pakete wie die folgenden zu installieren.

[file: 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

Sobald das Powershell-Skript beendet ist, führt das Cmd-Skript weitere Aufgaben aus. Beachten Sie jetzt, dass cmd nach Abschluss der Task immer noch keinen Zugriff auf die neuen Umgebungsvariablen hat, selbst wenn das Powershell-Skript diese in seiner eigenen Sitzung aktualisiert hat. Aus diesem Grund führen wir alle erforderlichen Aufgaben im Powershell-Skript aus, die natürlich dieselben Befehle wie cmd aufrufen können.

1
Andy McRae

Es gibt keinen geraden Weg, wie Kev sagte. In den meisten Fällen ist es einfacher, eine andere CMD-Box zu erzeugen. Noch ärgerlicher ist, dass laufende Programme ebenfalls keine Änderungen bemerken (obwohl IIRC möglicherweise eine Broadcast-Nachricht anzeigt, um über solche Änderungen informiert zu werden).

Es war schlimmer: In älteren Windows-Versionen mussten Sie sich abmelden und dann wieder anmelden, um die Änderungen zu berücksichtigen ...

1
PhiLho

Wenn Sie Umgebungsvariablen in Windows nur aktualisieren müssen, führen Sie refreshenv von Ihrem Terminal aus aus, bevor Sie den PC neu starten.

1
Jasper

Ich benutze dieses Powershell-Skript, um die Variable PATH hinzuzufügen. Mit ein wenig Anpassung kann es auch in Ihrem Fall funktionieren, glaube ich.

#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

nein, ich glaube nicht ... Sie können sie jedoch manuell einstellen. So können Sie sie in eine Batch-Datei oder so etwas setzen.

möglicherweise könnte ein Hilfsprogramm/Skript erstellt werden (falls dies noch nicht geschehen ist), das die Registrierung abfragt und die aktuelle Umgebung als identisch einstellt

0
Keith Nicholas

Bearbeiten: Dies funktioniert nur, wenn die von Ihnen vorgenommenen Umgebungsänderungen auf die Ausführung einer Batchdatei zurückzuführen sind.

Wenn eine Stapeldatei mit SETLOCAL beginnt, wird sie beim Beenden immer in die ursprüngliche Umgebung zurückgeführt, auch wenn Sie vergessen haben, ENDLOCAL aufzurufen, bevor der Stapel beendet wird, oder wenn sie unerwartet abgebrochen wird.

Fast jede Batch-Datei, die ich schreibe, beginnt mit SETLOCAL, da ich in den meisten Fällen nicht möchte, dass die Nebenwirkungen von Umgebungsänderungen bestehen bleiben. In Fällen, in denen bestimmte Umgebungsvariablenänderungen außerhalb der Batch-Datei übertragen werden sollen, sieht mein letztes ENDLOCAL folgendermaßen aus:

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