The system PATH
变量的值存储在 Windows 注册表中Path
类型的REG_EXPAND_SZ
包含对环境变量的引用,例如%SystemRoot%
或者如果不正确,则由类型的应用程序修改REG_SZ
注册表项下没有环境变量引用:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
The user PATH
默认情况下,Windows 注册表中不存在变量。它存储在 Windows 注册表中,其值是Path
类型的REG_EXPAND_SZ
or REG_SZ
一旦由应用程序创建或由用户在注册表项下手动创建:
HKEY_CURRENT_USER\Environment
外部命令REG用命令QUERY
可以用来read的价值system or the user PATH
变量直接来自 Windows 注册表,具有标准用户权限。
可以阅读user PATH
来自 Windows 注册表的变量并将其值分配给环境变量UserPath
另外扩展目录路径列表中的所有环境变量。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "UserPath="
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do if /I "%%G" == "Path" (
if /I "%%H" == "REG_EXPAND_SZ" (call set "UserPath=%%I") else if /I "%%H" == "REG_SZ" set "UserPath=%%I"
if defined UserPath goto UserPathRead
)
echo User PATH is not defined or has no string value.
goto EndBatch
:UserPathRead
setlocal EnableDelayedExpansion
echo The user PATH is: !UserPath!
endlocal
:EndBatch
echo/
pause
endlocal
输出格式为reg query
取决于 Windows 版本,这使得附加不区分大小写IF必要的条件。有关详细信息reg query
输出格式参见示例使用 REG 查询读取 NT 的注册表 https://www.robvanderwoude.com/ntregquery.php由罗布·范德沃德撰写。
示例输出reg query HKCU\Environment /v Path
在 Windows XP 上:
! REG.EXE VERSION 3.0
HKEY_CURRENT_USER\Environment
Path REG_SZ C:\BatUtils
输出的开头有一个空行,末尾有一个空行,还有一个标题行,在包含注册表项的行上方还有一个空行。
包含感兴趣数据的行以四个空格字符开头,接下来是注册表值的不区分大小写的名称Path
。然后一个单个水平制表符字符被输出到注册表值类型REG_SZ
。最后还有一个水平制表符字符串值之前的字符Path
是可能包含一个或多个空格字符的输出。
示例输出reg query HKCU\Environment /v Path
在 Windows Vista 上或更新的 Windows 版本:
HKEY_CURRENT_USER\Environment
Path REG_SZ C:\BatUtils
输出的开头还有一个空行,末尾还有一个空行。但没有标题。第二行已包含注册表项。
包含感兴趣数据的行以四个空格字符开头,接下来是注册表值的不区分大小写的名称Path
. Then 四个空格而不是选项卡的输出留给注册表值类型REG_SZ
。最后还有四个空格而不是字符串值之前的制表符Path
是还可以包含一个或多个空格字符的输出。
命令REG在后台的单独命令进程中执行FOR。输出的错误信息为REG处理STDERR如果是注册表项HKCU\Environment
或值Path
通过将不存在的内容重定向到设备来抑制NUL with 2>nul
。重定向运算符>
必须在此处使用脱字符号进行转义^
在解析时被解释为文字字符FOR由 Windows 命令解释器执行的命令行,但在以后执行时作为重定向操作符REG单独后台命令进程中的命令行。
The FOR选项定义为"skip=2 tokens=1,2*"
导致跳过前两行REG输出并使用默认分隔符空格和制表符将其他行分成三个子字符串(标记)。
第一个空格/制表符分隔的字符串被分配给第一个循环变量G
这是到达感兴趣数据行时变量的名称。
第二个子字符串是注册表值类型,分配给循环变量H
成为下一个角色ASCII 表 https://www.asciitable.com/。这种行为的原因是FOR循环变量区分大小写。
第二个子字符串之后的空格/制表符之后的所有内容都分配给循环变量I
不分割线的其余部分,因为*
在选项字符串之后tokens=1,2
.
因此,在 Windows Vista 和更高版本的 Windows 上,该命令FOR处理作为输出的第一行REG线与Path
而在 Windows XP 上,处理的第一行是包含注册表项的行,这就是第一行的原因IF条件是必要的。
第二IF条件进行不区分大小写的字符串比较,以找出具有名称的注册表值的类型Path
。分配给的字符串Path
包含类型REG_EXPAND_SZ
一个或多个环境变量引用。由于这个原因,命令call
用于解析从注册表读取的字符串值并将其分配给循环变量I
由 Windows 命令处理器在命令之前展开所有环境变量引用SET执行以将扩展的字符串值分配给环境变量UserPath
.
Note: cmd.exe
搜索具有名称的可执行文件或脚本set
使用本地环境变量PATHEXT
and PATH
因为使用命令CALL。命令CALL设计用于从批处理文件中调用批处理文件,而不是强制 Windows 命令处理器再次解析命令行。
第三IF仅当注册表值达到时才执行条件Path
不属于类型REG_EXPAND_SZ
。它将不区分大小写的注册表值类型与字符串进行比较REG_SZ
在这种情况下,字符串值Path
可以直接赋值给环境变量UserPath
.
环境变量UserPath
上面明确未定义FOR环形。所以如果当前行有第一个字符串Path
无论如何,注册表值类型是REG_EXPAND_SZ
or REG_SZ
,现在应该定义环境变量UserPath
否则有一个注册表值Path
类型错误或空字符串。有可能有Path
以空字符串存储在 Windows 注册表中,但无法定义环境变量UserPath
带有一个空字符串。
第四个IF条件验证环境变量UserPath
实际上是用非空字符串定义的。在这种情况下命令GOTO用于退出FOR成功读取后循环user PATH
通过跳转到命令块来进一步处理环境变量,从 Windows 注册表中获取变量UserPath
.
下面的命令块FOR如果达到循环user PATH
Windows 注册表中根本不存在变量,或者类型错误,或者存在空字符串。
为了完整起见,批处理代码
- read system AND user
PATH
来自Windows注册表而不扩展,
- 连接两者
PATH
变量到PATH
与覆盖local PATH
在当前环境下的当前命令进程中,
- 如果有必要,现在展开所有环境变量引用。
- 全部替换
;;
by ;
in PATH
值和
- remove
;
从年底开始PATH
值(如果有的话)。
该批处理代码不检查是否user PATH
包含一个或多个已存在的目录路径system PATH
在连接它们之前。所以目录路径可能位于local PATH
终于出现不止一次了。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Get directly from Windows registry the system PATH variable value.
set "PathExpand="
set "PathSystem="
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do if /I "%%G" == "Path" (
if /I "%%H" == "REG_EXPAND_SZ" (set "PathExpand=1" & set "PathSystem=%%I") else if /I "%%H" == "REG_SZ" set "PathSystem=%%I"
if defined PathSystem goto GetUserPath
)
rem Get directly from Windows registry the user PATH variable value.
:GetUserPath
set "PathUser="
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do if /I "%%G" == "Path" (
if /I "%%H" == "REG_EXPAND_SZ" (set "PathExpand=1" & set "PathUser=%%I") else if /I "%%H" == "REG_SZ" set "PathUser=%%I"
if defined PathUser goto SetPath
)
rem Concatenate the two PATH values to a single value.
rem Expand the environment variable references if that is necessary at all.
rem Next replace all two consecutive semicolons by a single semicolon.
rem Last remove semicolon from end of the directories list if there is one.
:SetPath
set "PATH=%PathSystem%;%PathUser%"
if defined PathExpand call set "PATH=%PATH%"
set "PATH=%PATH:;;=;%"
if "%PATH:~-1%" == ";" set "PATH=%PATH:~0,-1%"
rem Output the environment variables PATH and PATHEXT and all other
rem environment variables starting case-insensitive with the string
rem Path as used in this batch file code to see what happened here.
set PATH
endlocal
为了了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
set /?
setlocal /?
另请阅读 Microsoft 的文章:使用命令重定向运算符 https://technet.microsoft.com/en-us/library/bb490982.aspx的解释2>nul
以及 Stack Overflow 主题的答案使用 Windows 批处理文件的单行多个命令 https://stackoverflow.com/a/25344009/3074564对于运算符的含义&
在命令行上。