Mof*_*ofi 14
系统变量存储在 Windows 注册表中,其值类型包含对环境变量的引用,例如, 如果不正确,则由注册表项下没有环境变量引用的类型的 \xc2\xa0 应用程序修改:PATH
Path
REG_EXPAND_SZ
%SystemRoot%
REG_SZ
HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment\n
Run Code Online (Sandbox Code Playgroud)\n默认情况下, PATH
Windows 注册表中不存在用户变量。它以Path
type 的值存储在 Windows 注册表中REG_EXPAND_SZ
,或者REG_SZ
由应用程序创建或由用户在注册表项下手动创建:
HKEY_CURRENT_USER\\Environment\n
Run Code Online (Sandbox Code Playgroud)\n外部命令REG with 命令QUERY
可用于以标准用户权限直接从 Windows 注册表读取系统或用户 变量的值PATH
。
可以从 Windows 注册表中读取用户 PATH
变量并将其值分配给环境变量UserPath
,同时扩展目录路径列表中的所有环境变量。
@echo off\nsetlocal EnableExtensions DisableDelayedExpansion\nset "UserPath="\nfor /F "skip=2 tokens=1,2*" %%G in (\'%SystemRoot%\\System32\\reg.exe query "HKCU\\Environment" /v "Path" 2^>nul\') do if /I "%%G" == "Path" (\n if /I "%%H" == "REG_EXPAND_SZ" (call set "UserPath=%%I") else if /I "%%H" == "REG_SZ" set "UserPath=%%I"\n if defined UserPath goto UserPathRead\n)\necho User PATH is not defined or has no string value.\ngoto EndBatch\n\n:UserPathRead\nsetlocal EnableDelayedExpansion\necho The user PATH is: !UserPath!\nendlocal\n\n:EndBatch\necho/\npause\nendlocal\n
Run Code Online (Sandbox Code Playgroud)\n的输出格式reg query
取决于 Windows 版本,这使得需要额外的不区分大小写的IF条件。有关reg query
输出格式的详细信息,请参阅Rob van der Woude 编写的使用 REG 查询读取 NT\'s 注册表的示例。
reg query HKCU\\Environment /v Path
Windows XP 上的示例输出:
\n! REG.EXE VERSION 3.0\n\nHKEY_CURRENT_USER\\Environment\n Path REG_SZ C:\\BatUtils\n\n
Run Code Online (Sandbox Code Playgroud)\n输出的开头有一个空行,末尾有一个空行,还有一个标题行,在包含注册表项的行上方还有一个空行。
\n包含感兴趣数据的行以四个空格字符开头,接下来是不区分大小写的注册表值名称Path
。然后向注册表值类型左侧输出一个水平制表REG_SZ
符。最后,在\xc2\xa0 的字符串值\xc2\xa0output 之前还有一个水平制表Path
符,也可以包含一个或多个空格字符。
reg query HKCU\\Environment /v Path
Windows Vista 或更高版本的 Windows 上的示例输出:
\nHKEY_CURRENT_USER\\Environment\n Path REG_SZ C:\\BatUtils\n\n
Run Code Online (Sandbox Code Playgroud)\n输出的开头还有一个空行,末尾还有一个空行。但没有标题。第二行已包含注册表项。
\n包含感兴趣数据的行以四个空格字符开头,接下来是不区分大小写的注册表值名称Path
。然后将四个空格而不是制表符输出到注册表值类型中REG_SZ
。最后,在输出的字符串值之前再次有四个空格Path
而不是制表符,该值还可以包含一个或多个空格字符。
命令REG由FOR在后台的单独命令进程中执行。在注册表项或值不存在的情况下,REG处理STDERR时输出的错误消息可通过将其重定向到设备NUL来抑制。重定向运算符必须在此处使用脱字符号进行转义,以便在 Windows 命令解释器解析FOR命令行时解释为文字字符,但在以后在单独的后台命令进程中执行REG命令行时将其解释为重定向运算符。HKCU\\Environment
Path
2>nul
>
^
定义的 FOR 选项会导致跳过REG输出的前两行,并使用默认分隔符空格和制表符将其他行分成三个子字符串(标记)。"skip=2 tokens=1,2*"
第一个空格/制表符分隔的字符串被分配给第一个循环变量G
,它是到达包含感兴趣数据的行时的变量名称。
作为注册表值类型的第二个子字符串被分配给作为ASCII 表H
中的下一个字符的循环变量。此行为是FOR循环变量区分大小写的原因。
第二个子字符串之后的空格/制表符之后的所有内容都被分配给循环变量,I
而不会分割该行的其余部分,因为*
在选项字符串之后tokens=1,2
。
因此,在 Windows Vista 和更高版本的 Windows 上, FOR命令作为REG输出的第一行进行处理,而Path
在 Windows XP 上,处理的第一行是包含注册表项的行,这就是为什么需要第一个IF条件的原因。
第二个IF条件进行不区分大小写的字符串比较,以找出 name 的注册表值的类型Path
。分配给的字符串Path
在类型上包含REG_EXPAND_SZ
一个或多个环境变量引用。因此,call
使用该命令会导致解析从注册表读取的字符串值,并由I
Windows 命令处理器分配给循环变量,以在执行命令SET将扩展的字符串值分配给环境变量之前展开所有环境变量引用UserPath
。
注意: 使用本地环境变量并由于使用命令CALLcmd.exe
来搜索具有名称的可执行文件或脚本。命令CALL旨在从批处理文件中调用批处理文件,而不是强制 Windows 命令处理器再次解析命令行。set
PATHEXT
PATH
仅当注册表值不是类型时才执行第三个IF条件。它将不区分大小写的注册表值类型与字符串进行比较,在这种情况下,可以将字符串值直接分配给环境变量。Path
REG_EXPAND_SZ
REG_SZ
Path
UserPath
环境变量在FORUserPath
循环上方显式未定义。因此,如果当前行在任何情况下都具有第一个字符串并且注册表值类型为或,则现在应该定义环境变量,否则存在类型错误或空字符串的注册表值。可以使用空字符串存储在 Windows 注册表中,但不可能使用空字符串定义环境变量。Path
REG_EXPAND_SZ
REG_SZ
UserPath
Path
Path
UserPath
第四个IF条件验证环境变量UserPath
是否确实使用非空字符串定义。在这种情况下,命令GOTO用于在成功从 Windows 注册表读取用户变量后退出FOR循环,方法是跳转到命令块以进一步处理环境变量。 PATH
UserPath
如果 Windows 注册表中根本不存在用户变量,或者类型错误,或者存在空字符串,则到达FOR循环下面的命令块。 PATH
为了完整起见,批处理代码
\nPATH
而不扩展,PATH
变量连接到当前环境中的当前命令进程中PATH
覆盖本地, PATH
;;
为;
in PATH
value 和;
从值的末尾删除。PATH
此批处理代码在连接它们之前不会检查用户 PATH
是否包含系统 PATH
中已存在的一个或多个目录路径。因此,一个目录路径可能在本地 PATH
最终出现多次。
@echo off\nsetlocal EnableExtensions DisableDelayedExpansion\nrem Get directly from Windows registry the system PATH variable value.\nset "PathExpand="\nset "PathSystem="\nfor /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" (\n if /I "%%H" == "REG_EXPAND_SZ" (set "PathExpand=1" & set "PathSystem=%%I") else if /I "%%H" == "REG_SZ" set "PathSystem=%%I"\n if defined PathSystem goto GetUserPath\n)\n\nrem Get directly from Windows registry the user PATH variable value.\n:GetUserPath\nset "PathUser="\nfor /F "skip=2 tokens=1,2*" %%G in (\'%SystemRoot%\\System32\\reg.exe query "HKCU\\Environment" /v "Path" 2^>nul\') do if /I "%%G" == "Path" (\n if /I "%%H" == "REG_EXPAND_SZ" (set "PathExpand=1" & set "PathUser=%%I") else if /I "%%H" == "REG_SZ" set "PathUser=%%I"\n if defined PathUser goto SetPath\n)\n\nrem Concatenate the two PATH values to a single value.\nrem Expand the environment variable references if that is necessary at all.\nrem Next replace all two consecutive semicolons by a single semicolon.\nrem Last remove semicolon from end of the directories list if there is one.\n\n:SetPath\nset "PATH=%PathSystem%;%PathUser%"\nif defined PathExpand call set "PATH=%PATH%"\nset "PATH=%PATH:;;=;%"\nif "%PATH:~-1%" == ";" set "PATH=%PATH:~0,-1%"\n\nrem Output the environment variables PATH and PATHEXT and all other\nrem environment variables starting case-insensitive with the string\nrem Path as used in this batch file code to see what happened here.\nset PATH\nendlocal\n
Run Code Online (Sandbox Code Playgroud)\n为了了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
\ncall /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
set /?
setlocal /?
另请阅读有关使用命令重定向运算符的 Microsoft 文章,了解 Stack Overflow 主题使用 Windows 批处理文件的单行多个命令的说明2>nul
和答案,了解命令行上运算符的含义。&