在Windows的命令提示符中是否有刷新环境变量的命令?

如果修改或添加环境变量,则必须重新启动命令提示符。是否有一个命令,我可以执行,将这样做而不重新启动CMD?

725977 次浏览

根据设计,Windows没有建在机制来将环境变量添加/更改/删除传播到已经运行的cmd.exe中,无论是从另一个cmd.exe还是从“我的电脑->属性->高级设置->环境变量”。

如果在现有的开放命令提示符范围之外修改或添加新的环境变量,则需要重新启动命令提示符,或者在现有的命令提示符中使用SET手动添加。

最新接受答案通过手动刷新脚本中的环境变量所有来显示部分解决方案。该脚本处理在“My Computer…”中全局更改环境变量的用例。但是如果一个环境变量在一个cmd.exe中被更改,脚本不会将其传播到另一个运行cmd.exe的环境变量中。

您可以使用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


# EYZ0:

我提出这个解决方案时遇到的两个主要问题是

我找不到一个直接的方法来将环境变量从vbs脚本导出回命令提示符,并且

PATH环境变量是用户变量和系统PATH变量的组合。

我不确定用户和系统之间的冲突变量的一般规则是什么,所以我选择让用户覆盖系统,除了在PATH变量中,它是专门处理的。

我使用奇怪的vbs+bat+临时bat机制来解决从vbs导出变量的问题。

请注意:该脚本不删除变量。

这可能是可以改进的。

添加

如果你需要将环境从一个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框更简单。更令人恼火的是,正在运行的程序也不知道这些变化(尽管IIRC可能有一个广播消息来查看此类变化的通知)。

更糟糕的是:在旧版本的Windows中,你必须先注销,然后再重新登录,才能考虑到这些变化……

调用这个函数对我来说很有用:

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

环境变量保存在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\Session Manager\Environment中。

许多有用的环境变量,如Path,都存储为REG_SZ。有几种方法可以访问注册表,包括REGEDIT:

# EYZ0 > < /代码

输出从神奇的数字开始。因此,要用find命令搜索它,需要输入并重定向:type <filename> | findstr -c:\"Path\"

所以,如果你只是想用系统属性刷新当前命令会话中的路径变量,下面的批处理脚本可以很好地工作:

RefreshPath.cmd:



@echo off


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


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


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


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


SETLOCAL EnableDelayedExpansion


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


ENDLOCAL


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

这适用于windows 7: SET PATH=%PATH%;C:\CmdShortcuts

通过输入echo %PATH%测试,它工作正常。也设置如果你打开一个新的cmd,不需要那些讨厌的重新启动:)

我想到的最好的方法是只做一个Registry查询。下面是我的例子。

在我的例子中,我使用批处理文件进行安装,并添加了新的环境变量。我需要在安装完成后立即做一些事情,但无法用这些新变量生成一个新进程。我测试了生成另一个资源管理器窗口,并回调cmd.exe,这是有效的,但在Vista和Windows 7上,资源管理器只作为单个实例运行,通常作为登录的人运行。这将失败的自动化,因为我需要我的管理信用做的事情,不管从本地系统运行或作为一个管理员在盒子上。这样做的限制是,它不能处理像路径这样的东西,这只适用于简单的环境变量。这允许我使用批处理进入一个目录(带空格),并复制文件运行。exe等。这篇文章来自五月资源网站stackoverflow.com

原批处理调用新批处理:

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
还有另一个方法,我从各种不同的想法中想出的。请看下文。这基本上会得到最新的路径变量从注册表然而,这将导致一些问题,因为注册表查询将给出变量本身,这意味着到处都有一个变量,这将不会工作,所以为了解决这个问题,我基本上加倍的路径。非常讨厌的。更可取的方法是: 设置路径= % %路径;C: \ Program Files \软件…\ < / p >

不管这是新的批处理文件,请谨慎使用。

@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

使用“setx”并重新启动cmd提示符

有一个名为“对于setx”的命令行工具用于该作业。 它用于阅读和写作 env变量。

.命令窗口关闭后,变量仍然存在

创建或修改用户或系统环境中的环境变量,而不需要编程或脚本。对于setx命令还检索注册表项的值并将它们写入文本文件。”

注意:通过此工具创建或修改的变量将在以后的命令窗口中可用,但在当前CMD.exe命令窗口中不可用。所以,你必须重新开始。

如果缺少setx:

  • http://download.microsoft.com/download/win2000platform/setx/1.00.0.1/nt5/en-us/setx_setup.exe < a href = " http://download.microsoft.com/download/win2000platform/setx/1.00.0.1/nt5/en-us/setx_setup.exe " > < / >

或修改注册表

# EYZ0说:

当需要通过编程方式添加或修改系统环境变量时,使用add 他们去 < >强HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ \控制会话 Manager\Environment注册表项,然后广播WM_SETTINGCHANGE . # 将lParam设置为字符串“环境”。< / p >

这允许应用程序(如shell)接收您的更新。

编辑:只有当您所做的环境更改是运行批处理文件的结果时,这才有效。

如果批处理文件以SETLOCAL开头,那么即使您在批处理退出前忘记调用ENDLOCAL,或者它意外中止,它也会在退出时解开回到原始环境。

几乎我编写的每个批处理文件都以SETLOCAL开头,因为在大多数情况下,我不希望环境变化的副作用仍然存在。在某些情况下,我确实希望某些环境变量的变化传播到批处理文件之外,然后我的最后ENDLOCAL看起来像这样:

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

可以通过在指定进程本身中覆盖环境表来实现这一点。

作为概念的证明,我写了这个示例应用程序,它只是在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_PARAMETERS结构来找到(例如在windbg# EYZ0和dt _RTL_USER_PROCESS_PARAMETERS中)

要将概念证明更改为OP需要的内容,只需枚举当前系统和用户环境变量(如@tsadok的答案所记录的那样),并将整个环境表写入目标进程的内存中。

环境块的大小也存储在_RTL_USER_PROCESS_PARAMETERS结构体中,但是内存分配在进程的堆上。所以从外部过程中,我们没有能力调整它的大小,让它变大。我尝试使用VirtualAllocEx在目标进程中为环境存储分配额外的内存,并能够设置和读取一个全新的表。不幸的是,任何试图从正常方式修改环境的尝试都将崩溃并烧毁,因为地址不再指向堆(它将在RtlSizeHeap中崩溃)。

在最终找到一个更简单的解决方案之前,我偶然发现了这个答案。

只需在任务管理器中重新启动explorer.exe

我没有测试,但您可能还需要重新打开命令提示符。

感谢Timo Huovinen: 虽然已成功安装,但无法识别节点(如果这对你有帮助,请把这个人的评论归功于他)。

我在批处理脚本中使用以下代码:

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

通过在对于SETX之后使用,可以直接使用“local”变量,而无需重新启动命令窗口。在下次运行时,将使用环境变量。

为了解决这个问题,我使用setx和set改变了环境变量,然后重新启动explorer.exe的所有实例。这样,随后启动的任何进程都将拥有新的环境变量。

我的批处理脚本这样做:

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


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

这种方法的问题是当前打开的所有资源管理器窗口都将被关闭,这可能是一个坏主意-但请参阅Kev的帖子来了解为什么这是必要的

以下是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 .

尝试以管理员身份打开一个新的命令提示符。我在Windows 10上使用了这个方法。(我知道这是一个老答案,但我不得不分享这个,因为不得不为这个写VBS脚本是荒谬的)。

我喜欢巧克力之后的方法,就像匿名懦夫的回答,因为这是一个纯粹的批量处理方法。但是,它会留下一个临时文件和一些临时变量。我给自己做了一个更干净的版本。

PATH上创建一个文件refreshEnv.bat。通过执行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.

在不重启当前会话的情况下,向路径中添加变量的最简单方法是打开命令提示符并输入:

PATH=(VARIABLE);%path%

并按输入

要检查变量是否已加载,请键入

PATH

并按输入。但是,在重新启动之前,该变量将只是路径的一部分。

我使用这个Powershell脚本添加到路径变量。 只要稍微调整一下,我相信它也适用于你的情况
#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%"

重新启动资源管理器为我做到了这一点,但只对新的cmd终端。

我设置路径的终端已经可以看到新的path变量了(在Windows 7中)。

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

如果它只涉及一个(或几个)你想改变的特定变量,我认为最简单的方法是解决方案:在你的环境和当前的控制台会话中设置

  • Set将把变量放在当前会话中
  • SetX将把变量放在环境中,但不是在当前会话中

我使用这个简单的批处理脚本将Maven从Java7更改为Java8(两者都是env。批处理文件夹在我的路径 var中,所以我总是可以调用“j8”,在我的控制台和环境中,我的JAVA_HOME var被更改:

j8.bat:

@echo off
set JAVA_HOME=%JAVA_HOME_8%
setx JAVA_HOME "%JAVA_HOME_8%"
到目前为止,我发现这是工作最好和最简单的。 你可能希望这是在一个命令中,但它只是没有在Windows

在Windows 7/8/10上,你可以安装Chocolatey,它有一个内置的脚本。

安装Chocolatey后,只需输入RefreshEnv.cmd

令人困惑的事情可能是,有几个地方开始cmd。 在我的情况下,我运行Windows资源管理器中的CMD和环境变量没有变化,而当启动CMD从“运行” (windows键+ r)环境变量被改变了.

在我的情况下,我只需要从任务管理器中杀死Windows资源管理器进程,然后从任务管理器中重新启动它

一旦我这样做了,我就可以从windows资源管理器衍生的cmd中访问新的环境变量。

谢谢你提出这个非常有趣的问题,即使在2019年(事实上,更新shell cmd并不容易,因为如上所述,它是一个单一的实例),因为在windows中更新环境变量允许完成许多自动化任务,而无需手动重新启动命令行。

例如,我们使用它来允许在我们定期重新安装的大量机器上部署和配置软件。我必须承认,在软件部署期间重新启动命令行是非常不切实际的,而且需要我们找到不一定令人愉快的变通办法。 让我们来解决问题。 我们按以下步骤进行。< / p >

1 -我们有一个批处理脚本,它依次调用powershell脚本

# EYZ0。

cmd # EYZ0

2 -在此之后,刷新。ps1脚本使用注册表键(GetValueNames()等)更新环境变量。 然后,在同一个powershell脚本中,我们只需要调用新的环境变量即可。 例如,在一个典型的情况下,如果我们之前刚刚用静默命令用cmd安装了nodeJS,在函数被调用后,我们可以直接调用npm来安装,在同一个会话中,如下所示的特定包。< / p >

(文件: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相同的命令。< / p >

我已经用了几年的解决方案:

@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

糟糕,这是更新的版本。

我做了一个更好的替代Chocolatey refreshenv cmd和cygwin,解决了很多问题,如:

    如果变量有一些巧克力,refreshenv就是 CMD元字符,请看这个测试:

    将此添加到HKCU\Environment: test & echo baaaaaaaaaad, 然后运行巧克力refreshenv,你会看到它打印出来 baaaaaaaaaad,这是非常糟糕的,新的路径没有添加到 你的路径变量

    这个脚本解决了这个问题,你可以用任何元字符测试它,甚至是像这样糟糕的东西:

    ; & % ' ( ) ~ + @ # $ { } [ ] , ` ! ^ | > < \ / " : ? * = . - _ & echo baaaad
    
  • refreshenv只添加系统用户 环境变量,但是CMD也添加了挥发性变量 (HKCU \动荡的环境)。这个脚本将合并所有三个和 删除任何重复的

  • refreshenv重置你的PATH。控件的新路径 调用此脚本的父脚本的旧路径。这样更好 而不是覆盖旧路径,否则会删除任何新路径 由父脚本添加的路径

  • 这个脚本解决了@Gene评论中描述的问题 Mayevsky: refreshenv 修改env变量TEMP和TMP替换 它们的值储存在HKCU\Environment中。在我的例子中,我运行 更新由Jenkins作业在slave上修改的env变量 在SYSTEM帐户下运行,因此TEMP和TMP被替换 使用%USERPROFILE%\AppData\Local\Temp代替c:\ windows \Temp这 中断构建,因为链接器无法打开系统概要文件的临时文件夹

我做了一个脚本cmd和另一个cygwin/bash, 你可以在这里找到它们:https://github.com/badrelmers/RefrEnv

对cmd

这个脚本使用vbscript,所以它可以在xp +的所有windows版本中工作

要使用它,将它保存为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>




cygwin / bash:

我不能在这里发布它,我达到了发布限制,所以从在这里下载

从bash调用它:source refrenv.sh

Powershell:

在这里下载

在Powershell中使用:. .\refrenv.ps1调用它

我只是想说,那些使用Anaconda的人,当你使用巧克力Refreshenv命令时;所有与conda相关的环境变量都将丢失。 要解决这个问题,最好的方法是重新启动CMD。(< / p >

这并没有直接回答你的问题,但如果你只是想要进程间通信,你可以使用PowerShell,你可以只使用剪贴板。

在一个过程中

Set-Clipboard(“MyText")

在单独的过程中

$ clipValue = Get-Clipboard

然后你可以使用clipValue作为任何其他字符串。这实际上使您能够使用CSV文本字符串将整个环境变量列表发送到另一个进程