Windows 명령어프롬프트에서 환경변수를 갱신하는 명령어가 있습니까?
환경변수를 수정하거나 추가할 경우 명령 프롬프트를 재시작해야 합니다.CMD를 재부팅하지 않고 실행할 수 있는 명령어가 있습니까?
Windows 7/8/10 에서는, 이 스크립트가 짜넣어져 있는 Chocolatey 를 인스톨 할 수 있습니다.
후 Chocolatey를 입력하면 .RefreshEnv.cmd
.
여기 Chocolatey가 사용하는 것이 있다.
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 "RefreshEnv.cmd only works from cmd.exe, please install the Chocolatey Profile to take advantage of refreshenv from PowerShell"
echo | set /p dummy="Refreshing environment variables from registry for cmd.exe. 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
:: capture user / architecture
SET "OriginalUserName=%USERNAME%"
SET "OriginalArchitecture=%PROCESSOR_ARCHITECTURE%"
:: Set these variables
call "%TEMP%\_env.cmd"
:: Cleanup
del /f /q "%TEMP%\_env.cmd" 2>nul
:: reset user / architecture
SET "USERNAME=%OriginalUserName%"
SET "PROCESSOR_ARCHITECTURE=%OriginalArchitecture%"
echo | set /p dummy="Finished."
echo .
vbs 스크립트를 사용하여 시스템 환경 변수를 캡처할 수 있지만 현재 환경 변수를 실제로 변경하려면 bat 스크립트가 필요하므로 결합된 솔루션입니다.
「」라고 하는 합니다.resetvars.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("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
이 코드가 포함된 다른 파일 이름 resetvars.bat을 같은 위치에 만듭니다.
@echo off
%~dp0resetvars.vbs
call "%TEMP%\resetvars.bat"
는, 「환경변수 갱신」을 해 주세요.resetvars.bat
변명:
이 해결책을 생각해 낸 두 가지 주요 문제는
a. vbs 스크립트에서 명령 프롬프트로 환경 변수를 내보내는 간단한 방법을 찾을 수 없었습니다.
b. PATH 환경변수는 사용자와 시스템 PATH 변수의 결합입니다.
사용자와 시스템 간의 충돌 변수에 대한 일반적인 규칙은 잘 모르기 때문에 특별히 처리되는 PATH 변수를 제외하고 사용자가 시스템을 덮어쓰도록 선택했습니다.
vbs에서 변수를 내보내는 문제를 해결하기 위해 이상한 vbs+bat+temporary bat 메커니즘을 사용합니다.
주의: 이 스크립트는 변수를 삭제하지 않습니다.
이것은 개선될 수 있을 것입니다.
추가된
cmd 창으로 할 이cmd」라고 ).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
실행합니다.exportvars.vbs
내보낼 창에서 내보낼 창으로 전환하고 다음과 같이 입력합니다.
"%TEMP%\resetvars.bat"
설계상 다른 cmd.exe 또는 "내 컴퓨터 -> 속성 -> 상세 설정 -> 환경 변수"에서 이미 실행 중인 cmd.exe에 환경 변수 추가/변경/삭제를 전파하는 내장 메커니즘은 없습니다.
기존 열린 명령어프롬프트 범위를 벗어나 새로운 환경변수를 변경하거나 추가할 경우 명령어프롬프트를 재시작하거나 기존 명령어프롬프트에서 SET를 사용하여 수동으로 추가해야 합니다.
마지막으로 승인된 답변에서는 스크립트의 모든 환경 변수를 수동으로 새로 고치는 부분적인 해결 방법을 보여 줍니다.이 스크립트는 "내 컴퓨터..."에서 환경 변수를 글로벌하게 변경하는 사용 사례를 처리합니다.환경변수". 단, 어떤 cmd.exe에서 환경변수가 변경되어도 스크립트는 cmd.exe를 실행하고 있는 다른 cmd.exe로 전파되지 않습니다.
나는 결국 더 쉬운 해결책을 찾기 전에 이 답을 발견했다.
재기동하기만 하면 .explorer.exe
[태스크 매니저]에서 선택합니다.
테스트하지 않았지만 명령 프롬프트를 다시 열어야 할 수도 있습니다.
Timo Huovinen의 크레딧: 정상적으로 설치되었지만 노드가 인식되지 않았습니다(이것이 도움이 된다면 이 사람의 코멘트 크레딧을 전달해 주세요).
은 Windows합니다.Windows 7에서 동작합니다.SET PATH=%PATH%;C:\CmdShortcuts
echo %PATH% 라고 입력하고 테스트한 결과, 정상적으로 동작했습니다.또, 새로운 cmd를 여는 경우에도, 번거로운 재기동은 불필요하게 됩니다. : )
"setx"를 사용하여 cmd 프롬프트를 재시작합니다.
이 작업에는 "setx"라는 명령줄 도구가 있습니다.환경 변수를 읽고 쓸 때 사용합니다.변수는 명령 창을 닫은 후에도 유지됩니다.
"프로그래밍이나 스크립팅 없이 사용자 또는 시스템 환경에서 환경 변수를 생성 또는 수정합니다.setx 명령어는 레지스트리 키 값도 가져와 텍스트 파일에 씁니다."
주의: 이 툴로 작성 또는 변경된 변수는 향후 명령어창에서는 사용할 수 있지만 현재 CMD.exe 명령어창에서는 사용할 수 없습니다.다시 시작해야 합니다.
ifsetx
다음 항목이 없습니다.
또는 레지스트리를 변경합니다.
MSDN은 다음과 같이 말합니다.
시스템 환경변수를 프로그래밍 방식으로 추가하거나 변경하려면 HKEY_LOCAL_MACHINE\System\에 추가합니다.CurrentControlSet\Control\세션 매니저\환경 레지스트리 키를 누른 다음 LParam이 "Environment" 문자열로 설정된 WM_SETTING CHANGE 메시지를 브로드캐스트합니다.
이를 통해 셸 등의 응용 프로그램이 업데이트를 선택할 수 있습니다.
이 함수를 호출하는 것이 나에게 효과가 있었습니다.
VOID Win32ForceSettingsChange()
{
DWORD dwReturnValue;
::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
}
제가 생각해낸 가장 좋은 방법은 레지스트리 쿼리를 실행하는 것입니다.여기 제 예가 있습니다.
이 예에서는 새로운 환경변수를 추가한 배치파일을 사용하여 설치를 실시했습니다.설치가 완료되자마자 이 작업을 수행해야 했지만 새로운 변수로는 새로운 프로세스를 생성할 수 없었습니다.다른 탐색기 창을 띄우는 것을 테스트하고 cmd.exe로 다시 호출했습니다만, Vista와 Windows 7에서는 탐색기는 단일 인스턴스로만 실행되며, 일반적으로 로그인한 사람이 실행이 됩니다.로컬 시스템에서 실행하든 관리자든 관리자든 작업을 수행하려면 관리자 자격 증명이 필요하기 때문에 자동화와 함께 실패할 수 있습니다.이에 대한 제한은 경로와 같은 것을 처리하지 않는다는 것입니다. 이는 단순한 환경 변수에서만 작동합니다.이것에 의해, 배지를 사용해 디렉토리(스페이스 포함)에 액세스 해, .exes등의 파일을 카피할 수 있게 되었습니다.이는 오늘 stackoverflow.com의 5월 리소스에서 작성되었습니다.
새로운 배치에 대한 Orginal Batch 호출:
testenvget.cmd SDROOT(또는 임의의 변수)
@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
그리고 제가 여러 가지 아이디어에서 생각해낸 또 다른 방법이 있습니다.아래를 참조해 주세요.이것은 기본적으로 레지스트리에서 최신 경로 변수를 가져옵니다.그러나 레지스트리 쿼리 자체가 변수를 제공하기 때문에 많은 문제가 발생합니다.즉, 변수가 있는 모든 곳에서 이 문제가 발생하지 않기 때문에 이 문제를 해결하기 위해 기본적으로 경로를 두 배로 늘립니다.아주 고약하다.보다 적합한 방법은 다음과 같습니다. Set Path=%Path%;C:\Program Files\Software...\
여기에 새로운 배치 파일이 있는 경우에도 주의해 주십시오.
@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
탐색기를 재시작하면 새 cmd 터미널에서만 이 작업을 수행할 수 있습니다.
경로를 설정한 단말기가 이미 새로운 경로 변수를 볼 수 있습니다(Windows 7).
taskkill /f /im explorer.exe && explorer.exe
이를 수행하려면 지정된 프로세스 내에서 환경 테이블을 덮어쓸 수 있습니다.
개념 증명으로 이 샘플 앱을 작성했습니다.이 앱은 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;
}
샘플 출력:
>set ENVTEST=abc
>cppTest.exe 13796
Target PID: 13796
PEB: 000007FFFFFD3000
UserProcessParameters: 00000000004B2F30
environment: 000000000052E700
Offset: 1528
>set ENVTEST
ENVTEST=def
메모들
이 접근방식은 보안 제한에도 한정됩니다.대상이 상위 레벨 또는 상위 계정(SYSTEM 등)에서 실행되는 경우 해당 메모리를 편집할 수 있는 권한이 없습니다.
32비트 앱에서 이 작업을 수행하려면 위의 하드 코드 오프셋이 각각 0x10 및 0x48로 변경됩니다. 및 수를 들어의 _PEB의 _RTL_USER_PROCESS_PARAMETIRS).dt _PEB
★★★★★★★★★★★★★★★★★」dt _RTL_USER_PROCESS_PARAMETERS
)
개념 증명을 OP가 필요로 하는 것으로 변경하려면 현재 시스템과 사용자 환경 변수(@tsadok의 답변에 의해 문서화된 것 등)를 열거하고 전체 환경 테이블을 대상 프로세스의 메모리에 쓰기만 하면 됩니다.
편집: 환경 블록의 크기는 _RTL_USER_PROCESS_PARAMETES 구조체에도 저장되지만 메모리는 프로세스의 힙에 할당됩니다.따라서 외부 프로세스에서는 크기를 조정하거나 더 크게 만들 수 없습니다.VirtualAllocEx를 사용하여 환경 스토리지의 타깃 프로세스에서 추가 메모리를 할당하는 작업을 진행하면서 완전히 새로운 테이블을 설정하고 읽을 수 있었습니다.유감스럽게도 통상적인 수단으로부터 환경을 변경하려고 하면, 주소가 히프를 가리키지 않게 되어 크래시 해 버립니다(RtlSizeHeap에서는 크래시 됩니다).
현재 세션에서 재부팅하지 않고 변수에 경로를 추가하는 가장 쉬운 방법은 명령 프롬프트를 열고 다음과 같이 입력하는 것입니다.
PATH=(VARIABLE);%path%
를 누릅니다.
변수가 로드되었는지 확인하려면
PATH
를 누릅니다.단, 변수는 재부팅할 때까지 경로의 일부만 됩니다.
저는 다음과 같은 많은 문제를 해결하는 cmd와 sygwin을 위한 Chocolatey refreshenv의 더 나은 대안을 만들었습니다.
변수에 몇 가지 cmd 메타 문자가 있으면 Chocolatey refreshenv는 매우 불량합니다.다음 테스트를 참조하십시오.
HKCU\Environment 합니다.
test & echo baaaaaaaaaad
초콜릿 같은 것을refreshenv
인쇄되어 것을 볼 수 있습니다.baaaaaaaaaad
이는 매우 불량하며 새 경로는 경로 변수에 추가되지 않습니다.이 스크립트는 이 문제를 해결하며 다음과 같은 매우 나쁜 메타 문자를 사용하여 테스트할 수 있습니다.
; & % ' ( ) ~ + @ # $ { } [ ] , ` ! ^ | > < \ / " : ? * = . - _ & echo baaaad
refreshenv는 시스템 및 사용자 환경 변수만 추가하지만 CMD는 휘발성 변수(HKCU\Volatile Environment)도 추가합니다.이 스크립트는 이 세 가지를 모두 병합하고 중복된 항목을 제거합니다.
refreshenv는 PATH를 리셋합니다.이 스크립트는 이 스크립트를 호출한 부모 스크립트의 이전 경로에 새 경로를 추가합니다.오래된 경로를 덮어쓰는 것보다 낫습니다. 덮어쓰지 않으면 부모 스크립트에 의해 새로 추가된 경로가 삭제됩니다.
이 스크립트는 @Gene Mayevsky의 코멘트에서 설명한 이 문제를 해결합니다.refreshenv는 환경변수 TEMP 및 TMP를 HKCU\Environment에 저장된 값으로 바꿉니다. 이 경우 SYSTEM 계정에서 실행되는 슬레이브 상에서 Jenkins 작업에 의해 변경된env 변수를 갱신하는 스크립트를 실행하여 TEMP와 TMP가 %USERPROFILE%\AppData\Local\로 대체되도록 합니다.C:\Windows 대신 Temp\Temp. 링커가 시스템 프로파일의 Temp 폴더를 열 수 없기 때문에 빌드가 중단됩니다.
cmd용 스크립트와 cygwin/cygwin용 스크립트를 각각 작성했습니다.https://github.com/badrelmers/RefrEnv 에서 찾을 수 있습니다.
cmd의 경우
이 스크립트는 vbscript를 사용하므로 모든 윈도우즈 버전 xp+에서 작동합니다.
그것을 refrenv.bat로 저장하고 호출합니다.call refrenv.bat
<!-- : Begin batch script
@echo off
REM PUSHD "%~dp0"
REM author: Badr Elmers 2021
REM description: refrenv = refresh environment. this is a better alternative to the chocolatey refreshenv for cmd
REM https://github.com/badrelmers/RefrEnv
REM https://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w
REM ___USAGE_____________________________________________________________
REM usage:
REM call refrenv.bat full refresh. refresh all non critical variables*, and refresh the PATH
REM debug:
REM to debug what this script do create this variable in your parent script like that
REM set debugme=yes
REM then the folder containing the files used to set the variables will be open. Then see
REM _NewEnv.cmd this is the file which run inside your script to setup the new variables, you
REM can also revise the intermediate files _NewEnv.cmd_temp_.cmd and _NewEnv.cmd_temp2_.cmd
REM (those two contains all the variables before removing the duplicates and the unwanted variables)
REM you can also put this script in windows\systems32 or another place in your %PATH% then call it from an interactive console by writing refrenv
REM *critical variables: are variables which belong to cmd/windows and should not be refreshed normally like:
REM - windows vars:
REM ALLUSERSPROFILE APPDATA CommonProgramFiles CommonProgramFiles(x86) CommonProgramW6432 COMPUTERNAME ComSpec HOMEDRIVE HOMEPATH LOCALAPPDATA LOGONSERVER NUMBER_OF_PROCESSORS OS PATHEXT PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITEW6432 PROCESSOR_IDENTIFIER PROCESSOR_LEVEL PROCESSOR_REVISION ProgramData ProgramFiles ProgramFiles(x86) ProgramW6432 PUBLIC SystemDrive SystemRoot TEMP TMP USERDOMAIN USERDOMAIN_ROAMINGPROFILE USERNAME USERPROFILE windir SESSIONNAME
REM ___INFO_____________________________________________________________
REM :: this script reload environment variables inside cmd every time you want environment changes to propagate, so you do not need to restart cmd after setting a new variable with setx or when installing new apps which add new variables ...etc
REM This is a better alternative to the chocolatey refreshenv for cmd, which solves a lot of problems like:
REM The Chocolatey refreshenv is so bad if the variable have some cmd meta-characters, see this test:
REM add this to the path in HKCU\Environment: test & echo baaaaaaaaaad, and run the chocolatey refreshenv you will see that it prints baaaaaaaaaad which is very bad, and the new path is not added to your path variable.
REM This script solve this and you can test it with any meta-character, even something so bad like:
REM ; & % ' ( ) ~ + @ # $ { } [ ] , ` ! ^ | > < \ / " : ? * = . - _ & echo baaaad
REM refreshenv adds only system and user environment variables, but CMD adds volatile variables too (HKCU\Volatile Environment). This script will merge all the three and remove any duplicates.
REM refreshenv reset your PATH. This script append the new path to the old path of the parent script which called this script. It is better than overwriting the old path, otherwise it will delete any newly added path by the parent script.
REM This script solve this problem described in a comment by @Gene Mayevsky: refreshenv modifies env variables TEMP and TMP replacing them with values stored in HKCU\Environment. In my case I run the script to update env variables modified by Jenkins job on a slave that's running under SYSTEM account, so TEMP and TMP get substituted by %USERPROFILE%\AppData\Local\Temp instead of C:\Windows\Temp. This breaks build because linker cannot open system profile's Temp folder.
REM ________
REM this script solve things like that too:
REM The confusing thing might be that there are a few places to start the cmd from. In my case I run cmd from windows explorer and the environment variables did not change while when starting cmd from the "run" (windows key + r) the environment variables were changed.
REM In my case I just had to kill the windows explorer process from the task manager and then restart it again from the task manager.
REM Once I did this I had access to the new environment variable from a cmd that was spawned from windows explorer.
REM my conclusion:
REM if I add a new variable with setx, i can access it in cmd only if i run cmd as admin, without admin right i have to restart explorer to see that new variable. but running this script inside my script (who sets the variable with setx) solve this problem and i do not have to restart explorer
REM ________
REM windows recreate the path using three places at less:
REM the User namespace: HKCU\Environment
REM the System namespace: HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
REM the Session namespace: HKCU\Volatile Environment
REM but the original chocolatey script did not add the volatile path. This script will merge all the three and remove any duplicates. this is what windows do by default too
REM there is this too which cmd seems to read when first running, but it contains only TEMP and TMP,so i will not use it
REM HKEY_USERS\.DEFAULT\Environment
REM ___TESTING_____________________________________________________________
REM to test this script with extreme cases do
REM :: Set a bad variable
REM add a var in reg HKCU\Environment as the following, and see that echo is not executed. if you use refreshenv of chocolatey you will see that echo is executed which is so bad!
REM so save this in reg:
REM all 32 characters: & % ' ( ) ~ + @ # $ { } [ ] ; , ` ! ^ | > < \ / " : ? * = . - _ & echo baaaad
REM and this:
REM (^.*)(Form Product=")([^"]*") FormType="[^"]*" FormID="([0-9][0-9]*)".*$
REM and use set to print those variables and see if they are saved without change ; refreshenv fail dramatically with those variables
REM invalid characters (illegal characters in file names) in Windows using NTFS
REM \ / : * ? " < > | and ^ in FAT
REM __________________________________________________________________________________________
REM __________________________________________________________________________________________
REM __________________________________________________________________________________________
REM this is a hybrid script which call vbs from cmd directly
REM :: The only restriction is the batch code cannot contain - - > (without space between - - > of course)
REM :: The only restriction is the VBS code cannot contain </script>.
REM :: The only risk is the undocumented use of "%~f0?.wsf" as the script to load. Somehow the parser properly finds and loads the running .BAT script "%~f0", and the ?.wsf suffix mysteriously instructs CSCRIPT to interpret the script as WSF. Hopefully MicroSoft will never disable that "feature".
REM :: https://stackoverflow.com/questions/9074476/is-it-possible-to-embed-and-execute-vbscript-within-a-batch-file-without-using-a
if "%debugme%"=="yes" (
echo RefrEnv - Refresh the Environment for CMD - ^(Debug enabled^)
) else (
echo RefrEnv - Refresh the Environment for CMD
)
set "TEMPDir=%TEMP%\refrenv"
IF NOT EXIST "%TEMPDir%" mkdir "%TEMPDir%"
set "outputfile=%TEMPDir%\_NewEnv.cmd"
REM detect if DelayedExpansion is enabled
REM It relies on the fact, that the last caret will be removed only in delayed mode.
REM https://www.dostips.com/forum/viewtopic.php?t=6496
set "DelayedExpansionState=IsDisabled"
IF "^!" == "^!^" (
REM echo DelayedExpansion is enabled
set "DelayedExpansionState=IsEnabled"
)
REM :: generate %outputfile% which contain all the new variables
REM cscript //nologo "%~f0?.wsf" %1
cscript //nologo "%~f0?.wsf" "%outputfile%" %DelayedExpansionState%
REM ::set the new variables generated with vbscript script above
REM for this to work always it is necessary to use DisableDelayedExpansion or escape ! and ^ when using EnableDelayedExpansion, but this script already solve this, so no worry about that now, thanks to God
REM test it with some bad var like:
REM all 32 characters: ; & % ' ( ) ~ + @ # $ { } [ ] , ` ! ^ | > < \ / " : ? * = . - _ & echo baaaad
REM For /f delims^=^ eol^= %%a in (%outputfile%) do %%a
REM for /f "delims== tokens=1,2" %%G in (%outputfile%) do set "%%G=%%H"
For /f delims^=^ eol^= %%a in (%outputfile%) do set %%a
REM for safely print a variable with bad charachters do:
REM SETLOCAL EnableDelayedExpansion
REM echo "!z9!"
REM or
REM set z9
REM but generally paths and environment variables should not have bad metacharacters, but it is not a rule!
if "%debugme%"=="yes" (
explorer "%TEMPDir%"
) else (
rmdir /Q /S "%TEMPDir%"
)
REM cleanup
set "TEMPDir="
set "outputfile="
set "DelayedExpansionState="
set "debugme="
REM pause
exit /b
REM #############################################################################
REM :: to run jscript you have to put <script language="JScript"> directly after ----- Begin wsf script --->
----- Begin wsf script --->
<job><script language="VBScript">
REM #############################################################################
REM ### put you code here #######################################################
REM #############################################################################
REM based on itsadok script from here
REM https://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w
REM and it is faster as stated by this comment
REM While I prefer the Chocolatey code-wise for being pure batch code, overall I decided to use this one, since it's faster. (~0.3 seconds instead of ~1 second -- which is nice, since I use it frequently in my Explorer "start cmd here" entry) –
REM and it is safer based on my tests, the Chocolatey refreshenv is so bad if the variable have some cmd metacharacters
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Set WshShell = WScript.CreateObject("WScript.Shell")
filename=WScript.Arguments.Item(0)
DelayedExpansionState=WScript.Arguments.Item(1)
TMPfilename=filename & "_temp_.cmd"
Set fso = CreateObject("Scripting.fileSystemObject")
Set tmpF = fso.CreateTextFile(TMPfilename, TRUE)
set oEnvS=WshShell.Environment("System")
for each sitem in oEnvS
tmpF.WriteLine(sitem)
next
SystemPath = oEnvS("PATH")
set oEnvU=WshShell.Environment("User")
for each sitem in oEnvU
tmpF.WriteLine(sitem)
next
UserPath = oEnvU("PATH")
set oEnvV=WshShell.Environment("Volatile")
for each sitem in oEnvV
tmpF.WriteLine(sitem)
next
VolatilePath = oEnvV("PATH")
set oEnvP=WshShell.Environment("Process")
REM i will not save the process env but only its path, because it have strange variables like =::=::\ and =F:=.... which seems to be added by vbscript
REM for each sitem in oEnvP
REM tmpF.WriteLine(sitem)
REM next
REM here we add the actual session path, so we do not reset the original path, because maybe the parent script added some folders to the path, If we need to reset the path then comment the following line
ProcessPath = oEnvP("PATH")
REM merge System, User, Volatile, and process PATHs
NewPath = SystemPath & ";" & UserPath & ";" & VolatilePath & ";" & ProcessPath
REM ________________________________________________________________
REM :: remove duplicates from path
REM :: expand variables so they become like windows do when he read reg and create path, then Remove duplicates without sorting
REM why i will clean the path from duplicates? because:
REM the maximum string length in cmd is 8191 characters. But string length doesnt mean that you can save 8191 characters in a variable because also the assignment belongs to the string. you can save 8189 characters because the remaining 2 characters are needed for "a="
REM based on my tests:
REM when i open cmd as user , windows does not remove any duplicates from the path, and merge system+user+volatil path
REM when i open cmd as admin, windows do: system+user path (here windows do not remove duplicates which is stupid!) , then it adds volatil path after removing from it any duplicates
REM ' https://www.rosettacode.org/wiki/Remove_duplicate_elements#VBScript
Function remove_duplicates(list)
arr = Split(list,";")
Set dict = CreateObject("Scripting.Dictionary")
REM ' force dictionary compare to be case-insensitive , uncomment to force case-sensitive
dict.CompareMode = 1
For i = 0 To UBound(arr)
If dict.Exists(arr(i)) = False Then
dict.Add arr(i),""
End If
Next
For Each key In dict.Keys
tmp = tmp & key & ";"
Next
remove_duplicates = Left(tmp,Len(tmp)-1)
End Function
REM expand variables
NewPath = WshShell.ExpandEnvironmentStrings(NewPath)
REM remove duplicates
NewPath=remove_duplicates(NewPath)
REM remove_duplicates() will add a ; to the end so lets remove it if the last letter is ;
If Right(NewPath, 1) = ";" Then
NewPath = Left(NewPath, Len(NewPath) - 1)
End If
tmpF.WriteLine("PATH=" & NewPath)
tmpF.Close
REM ________________________________________________________________
REM :: exclude setting variables which may be dangerous to change
REM when i run a script from task scheduler using SYSTEM user the following variables are the differences between the scheduler env and a normal cmd script, so i will not override those variables
REM APPDATA=D:\Users\LLED2\AppData\Roaming
REM APPDATA=D:\Windows\system32\config\systemprofile\AppData\Roaming
REM LOCALAPPDATA=D:\Users\LLED2\AppData\Local
REM LOCALAPPDATA=D:\Windows\system32\config\systemprofile\AppData\Local
REM TEMP=D:\Users\LLED2\AppData\Local\Temp
REM TEMP=D:\Windows\TEMP
REM TMP=D:\Users\LLED2\AppData\Local\Temp
REM TMP=D:\Windows\TEMP
REM USERDOMAIN=LLED2-PC
REM USERDOMAIN=WORKGROUP
REM USERNAME=LLED2
REM USERNAME=LLED2-PC$
REM USERPROFILE=D:\Users\LLED2
REM USERPROFILE=D:\Windows\system32\config\systemprofile
REM i know this thanks to this comment
REM The solution is good but it modifies env variables TEMP and TMP replacing them with values stored in HKCU\Environment. In my case I run the script to update env variables modified by Jenkins job on a slave that's running under SYSTEM account, so TEMP and TMP get substituted by %USERPROFILE%\AppData\Local\Temp instead of C:\Windows\Temp. This breaks build because linker cannot open system profile's Temp folder. – Gene Mayevsky Sep 26 '19 at 20:51
REM Delete Lines of a Text File Beginning with a Specified String
REM those are the variables which should not be changed by this script
arrBlackList = Array("ALLUSERSPROFILE=", "APPDATA=", "CommonProgramFiles=", "CommonProgramFiles(x86)=", "CommonProgramW6432=", "COMPUTERNAME=", "ComSpec=", "HOMEDRIVE=", "HOMEPATH=", "LOCALAPPDATA=", "LOGONSERVER=", "NUMBER_OF_PROCESSORS=", "OS=", "PATHEXT=", "PROCESSOR_ARCHITECTURE=", "PROCESSOR_ARCHITEW6432=", "PROCESSOR_IDENTIFIER=", "PROCESSOR_LEVEL=", "PROCESSOR_REVISION=", "ProgramData=", "ProgramFiles=", "ProgramFiles(x86)=", "ProgramW6432=", "PUBLIC=", "SystemDrive=", "SystemRoot=", "TEMP=", "TMP=", "USERDOMAIN=", "USERDOMAIN_ROAMINGPROFILE=", "USERNAME=", "USERPROFILE=", "windir=", "SESSIONNAME=")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objTS = objFS.OpenTextFile(TMPfilename, ForReading)
strContents = objTS.ReadAll
objTS.Close
TMPfilename2= filename & "_temp2_.cmd"
arrLines = Split(strContents, vbNewLine)
Set objTS = objFS.OpenTextFile(TMPfilename2, ForWriting, True)
REM this is the equivalent of findstr /V /I /L or grep -i -v , i don t know a better way to do it, but it works fine
For Each strLine In arrLines
bypassThisLine=False
For Each BlackWord In arrBlackList
If Left(UCase(LTrim(strLine)),Len(BlackWord)) = UCase(BlackWord) Then
bypassThisLine=True
End If
Next
If bypassThisLine=False Then
objTS.WriteLine strLine
End If
Next
REM ____________________________________________________________
REM :: expand variables because registry save some variables as unexpanded %....%
REM :: and escape ! and ^ for cmd EnableDelayedExpansion mode
set f=fso.OpenTextFile(TMPfilename2,ForReading)
REM Write file: ForAppending = 8 ForReading = 1 ForWriting = 2 , True=create file if not exist
set fW=fso.OpenTextFile(filename,ForWriting,True)
Do Until f.AtEndOfStream
LineContent = f.ReadLine
REM expand variables
LineContent = WshShell.ExpandEnvironmentStrings(LineContent)
REM _____this part is so important_____
REM if cmd delayedexpansion is enabled in the parent script which calls this script then bad thing happen to variables saved in the registry if they contain ! . if var have ! then ! and ^ are removed; if var do not have ! then ^ is not removed . to understand what happens read this :
REM how cmd delayed expansion parse things
REM https://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
REM For each parsed token, first check if it contains any !. If not, then the token is not parsed - important for ^ characters. If the token does contain !, then scan each character from left to right:
REM - If it is a caret (^) the next character has no special meaning, the caret itself is removed
REM - If it is an exclamation mark, search for the next exclamation mark (carets are not observed anymore), expand to the value of the variable.
REM - Consecutive opening ! are collapsed into a single !
REM - Any remaining unpaired ! is removed
REM ...
REM Look at next string of characters, breaking before !, :, or <LF>, and call them VAR
REM conclusion:
REM when delayedexpansion is enabled and var have ! then i have to escape ^ and ! ,BUT IF VAR DO NOT HAVE ! THEN DO NOT ESCAPE ^ .this made me crazy to discover
REM when delayedexpansion is disabled then i do not have to escape anything
If DelayedExpansionState="IsEnabled" Then
If InStr(LineContent, "!") > 0 Then
LineContent=Replace(LineContent,"^","^^")
LineContent=Replace(LineContent,"!","^!")
End If
End If
REM __________
fW.WriteLine(LineContent)
Loop
f.Close
fW.Close
REM #############################################################################
REM ### end of vbscript code ####################################################
REM #############################################################################
REM this must be at the end for the hybrid trick, do not remove it
</script></job>
sigwin/bash의 경우:
게시 제한에 도달했으므로 여기에서 다운로드하십시오.
it with : bash :source refrenv.sh
Powershell의 경우:
여기서 다운로드하다
Powershell로 :. .\refrenv.ps1
환경변수는 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\에 저장됩니다.세션 매니저\환경.
Path와 같은 많은 유용한 env vars는 REG_SZ로 저장됩니다.레지스트리에 액세스 하려면 , REGED 를 포함한 몇개의 방법이 있습니다.IT:
REGEDIT /E <filename> "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"
이치노하려면 find find를 리다이렉트해야 .type <filename> | findstr -c:\"Path\"
따라서 현재 명령 세션의 경로 변수를 시스템 속성에 있는 것으로 새로 고치는 경우 다음 배치 스크립트가 제대로 작동합니다.
Refresh Path.cmd:
@오프 REM 이 솔루션은 레지스트리에서 읽기 위해 권한 상승을 요구합니다. %syslog%\env.reg del %syslog%\env.reg /q /f가 존재하는 경우 REGEDIT /E %temp%\env.reg "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\"세션 매니저\환경" 존재하지 않는 경우 %syslog%\env.reg (echo "온도 위치에 레지스트리를 쓸 수 없습니다"출구 1) SETLOCAL EnableDelayedExpansion(SETLOCAL 활성화 지연 확장) /f "delimes==1,2* delimes==" %%i in ('%delimes%\env.reg ^| findstr -c:"Path\"=')는 다음과 같습니다.setath=%%~jecho!upath:\\=\!>%sech%\newpath) 최종 로컬 /f "path=*" %%i in (%path%\newpath)의 경우 경로=%%i를 설정합니다.
관리자 권한으로 새 명령 프롬프트를 열어 보십시오.Windows 10 에서는 이 방법이 효과가 있었습니다.(이것이 오래된 대답인 것은 알지만, 이것만으로 VBS 스크립트를 작성해야 하기 때문에 공유하지 않을 수 없었습니다.)
cmd를 시작할 수 있는 위치가 몇 개 없다는 점이 혼란스러울 수 있습니다.내 경우 Windows 탐색기에서 cmd를 실행했는데 환경 변수가 변경되지 않았고 "run"(Windows 키 + r)에서 cmd를 시작할 때 환경 변수가 변경되었습니다.
제 경우 태스크 매니저에서 윈도 탐색기 프로세스를 종료하고 태스크 매니저에서 다시 시작해야 했습니다.
이렇게 하면 Windows 탐색기에서 생성된 cmd에서 새 환경 변수에 액세스할 수 있습니다.
배치 스크립트에서 다음 코드를 사용합니다.
if not defined MY_ENV_VAR (
setx MY_ENV_VAR "VALUE" > nul
set MY_ENV_VAR=VALUE
)
echo %MY_ENV_VAR%
SETX 뒤에 SET를 사용하면 명령 창을 다시 시작하지 않고 "로컬" 변수를 직접 사용할 수 있습니다.그리고 다음 실행에서는 환경 변수가 사용됩니다.
변경할 특정 변수(또는 몇 개)만 관련된 경우 가장 쉬운 방법은 회피책이라고 생각합니다.사용 환경과 현재 콘솔 세션에서 설정하기만 하면 됩니다.
- Set은 현재 세션에 변수를 배치합니다.
- SetX는 환경에 var를 배치하지만 현재 세션에는 배치하지 않습니다.
Maven을 Java7에서 Java8로 변경하기 위한 간단한 배치 스크립트가 있습니다(둘 다 env. vars).배치 폴더는 PATH var에 있기 때문에 항상 'j8'을 호출할 수 있으며 콘솔 내 및 환경에서 JAVA_를 호출할 수 있습니다.HOME 변수 변경:
j8.bat:
@echo off
set JAVA_HOME=%JAVA_HOME_8%
setx JAVA_HOME "%JAVA_HOME_8%"
지금까지는 이게 가장 쉽고 잘 작동하는 것 같아요.이 명령어를 하나의 명령어로 사용하고 싶겠지만 Windows에는 없습니다.
몇 년 전부터 사용하고 있는 솔루션:
@echo off
rem Refresh PATH from registry.
setlocal
set USR_PATH=
set SYS_PATH=
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH') do @set "SYS_PATH=%%P %%Q"
for /F "tokens=3* skip=2" %%P in ('%SystemRoot%\system32\reg.exe query "HKCU\Environment" /v PATH') do @set "USR_PATH=%%P %%Q"
if "%SYS_PATH:~-1%"==" " set "SYS_PATH=%SYS_PATH:~0,-1%"
if "%USR_PATH:~-1%"==" " set "USR_PATH=%USR_PATH:~0,-1%"
endlocal & call set "PATH=%SYS_PATH%;%USR_PATH%"
goto :EOF
편집: 우와, 업데이트 버전입니다.
익명의 겁쟁이의 답변에 게재된 것처럼 초콜릿이 뒤따르는 접근법이 순수한 일괄 접근법이기 때문에 마음에 들었습니다.그러나 임시 파일과 일부 임시 변수가 남아 있습니다.나는 나를 위해 깔끔한 버전을 만들었다.
을 만듭니다.refreshEnv.bat
PATH
고칩니다.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.
2019년에도 흥미로운 질문을 게시해 주셔서 감사합니다(실제로, 위에서 언급한 바와 같이 단일 인스턴스이기 때문에 셸 cmd를 갱신하는 것은 쉽지 않습니다). 윈도에서 환경 변수를 갱신하면 명령줄을 수동으로 재시작하지 않고도 많은 자동화 작업을 수행할 수 있기 때문입니다.
예를 들어 정기적으로 재설치하는 다수의 머신에 소프트웨어를 도입 및 구성할 수 있도록 하기 위해 사용합니다.또한 소프트웨어 도입 중에 명령줄을 재시작해야 하는 것은 매우 비현실적이며 반드시 만족스럽지 않은 회피책을 찾아야 합니다.우리 문제로 들어가자.아래와 같이 진행하겠습니다.
1 - 이와 같은 powershell 스크립트를 호출하는 배치 스크립트가 있습니다.
[파일: task.filename]
cmd> powershell.exe -executionpolicy unrestricted -File C:\path_here\refresh.ps1
2 - 그 후 refresh.ps1 스크립트는 레지스트리 키(GetValueNames() 등)를 사용하여 환경변수를 갱신합니다.그런 다음 동일한 powershell 스크립트에서 사용 가능한 새로운 환경 변수를 호출하면 됩니다.예를 들어, 일반적인 경우 노드를 방금 설치한 경우이전에는 사일런트 명령어를 사용하여 JS를 사용하여 함수를 호출한 후 npm을 직접 호출하여 다음과 같은 특정 패키지를 같은 세션에 설치할 수 있습니다.
[파일: 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
powershell 스크립트가 끝나면 cmd 스크립트는 다른 작업과 함께 진행됩니다.여기서 한 가지 유의해야 할 점은 작업이 완료된 후에도 cmd는 새 환경 변수에 액세스할 수 없다는 것입니다. powershell 스크립트가 자체 세션의 변수를 업데이트한 경우에도 마찬가지입니다.따라서 powershell 스크립트에서 cmd와 동일한 명령어를 호출할 수 있는 모든 필요한 작업을 수행합니다.
Kev가 말했듯이, 곧은 길은 없다.대부분의 경우 다른 CMD 상자를 생성하는 것이 더 간단합니다.더 짜증나는 것은 실행 중인 프로그램도 변경을 인식하지 못한다는 점입니다(IIRC에서는 이러한 변경을 통지받기 위해 브로드캐스트메시지가 표시될 수 있습니다).
이전 버전의 Windows에서는 변경을 고려하기 위해 로그오프했다가 다시 로그백해야 했습니다.
이 Powershell 스크립트를 사용하여 PATH 변수에 추가합니다.조금만 조정하면 당신의 경우에도 효과가 있을 거라고 생각합니다.
#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%"
편집: 이 기능은 배치 파일을 실행한 결과로 환경이 변경된 경우에만 작동합니다.
배치 파일이 다음과 같이 시작되는 경우SETLOCAL
전화하는 것을 잊어도 항상 원래 환경으로 돌아갑니다.ENDLOCAL
배치가 종료되기 전 또는 예기치 않게 중단되는 경우.
쓰는 거의 모든 배치파일은 다음과 같이 시작합니다.SETLOCAL
대부분의 경우 환경변화의 부작용이 남는 것을 원치 않기 때문입니다.특정 환경변수 변경을 배치 파일 외부로 전파하고 싶은 경우 마지막 환경변수 변경 후ENDLOCAL
다음과 같습니다.
ENDLOCAL & (
SET RESULT1=%RESULT1%
SET RESULT2=%RESULT2%
)
이 문제를 해결하기 위해 setx와 set를 모두 사용하여 환경변수를 변경한 후 explor.exe의 모든 인스턴스를 재시작했습니다.이렇게 하면 이후에 시작된 모든 프로세스가 새로운 환경 변수를 갖게 됩니다.
이를 위한 배치 스크립트:
setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"
taskkill /f /IM explorer.exe
start explorer.exe >nul
exit
이 접근법의 문제는 현재 열려 있는 탐색기 창이 모두 닫히는 것입니다.이것은 아마도 나쁜 생각일 것입니다.그러나 이것이 필요한 이유에 대해서는, Kev의 투고를 참조해 주세요.
아나콘다를 사용하는 사람들은 초콜릿과 초콜릿과Refreshenv
명령어. conda와 관련된 모든 환경변수가 손실됩니다.이 문제를 해결하려면 CMD를 재시작하는 것이 가장 좋습니다. : (
이 방법으로 질문에 직접 답할 수는 없지만 프로세스 간 통신만 원할 뿐 PowerShell을 사용할 수 있다면 클립보드를 사용할 수 있습니다.
하나의 프로세스로
Set-Clipboard ("MyText")
별도 프로세스 중
$clipValue=클립보드 가져오기
clipValue를 다른 문자열로 사용할 수 있습니다.이를 통해 CSV 텍스트 문자열을 사용하여 환경변수 목록 전체를 다른 프로세스로 전송할 수 있습니다.
대부분의 경우 열려 있거나 실행 중인 응용 프로그램에서 업데이트된 환경 변수에 액세스할 수 있어야 합니다.따라서 어플리케이션을 닫거나 다시 열면 갱신된 환경변수가 선택됩니다.
이면에는 매우 미묘한 차이가 있지만, 위의 내용은 대부분의 사용 사례에 적용됩니다.
언급URL : https://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w
'programing' 카테고리의 다른 글
Swift 3에서 커스텀 알림을 작성하려면 어떻게 해야 합니까? (0) | 2023.04.10 |
---|---|
awk 또는 sed를 사용하여 문자열을 재귀적으로 검색/교체하려면 어떻게 해야 합니까? (0) | 2023.04.10 |
Windows 및 Linux에서의 C++ 컴파일: ifdef 스위치 (0) | 2023.04.10 |
Windows에서 스크린샷을 파일에 직접 저장하려면 어떻게 해야 합니까? (0) | 2023.04.10 |
Echo newline in Bash prints 리터럴 \n (0) | 2023.04.10 |