【问题标题】:How to get only the user path variable?如何仅获取用户路径变量?
【发布时间】:2017-05-12 09:30:23
【问题描述】:

Echo %PATH% 返回 system PATH 变量 + user PATH 变量。

如何只获取 user PATH 变量?

【问题讨论】:

    标签: batch-file


    【解决方案1】:

    系统 PATH 变量存储在 Windows 注册表中,其值为 Path 类型为 REG_EXPAND_SZ 包含对环境变量(如 %SystemRoot%)的引用,或者如果不正确则由类型的应用程序修改REG_SZ 注册表项下没有环境变量引用:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment
    

    默认情况下,Windows 注册表中不存在 user PATH 变量。它存储在 Windows 注册表中,值 Path 类型为 REG_EXPAND_SZREG_SZ,一旦由应用程序创建或由用户在注册表项下手动创建:

    HKEY_CURRENT_USER\Environment
    

    带有命令QUERY的外部命令REG可用于读取系统用户 PATH 变量直接来自具有标准用户权限的 Windows 注册表。

    可以从 Windows 注册表中读取 user PATH 变量,并将其值分配给环境变量 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 输出格式的详细信息,请参阅 Rob van der Woude 编写的 Reading NT's Registry with REG Query

    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。然后四个空格而不是一个制表符被输出到注册表值类型REG_SZ。最后,在输出Path 的字符串值之前还有四个空格,而不是一个制表符,它还可以包含一个或多个空格字符。

    REG命令由FOR在后台单独的命令进程中执行。 REG 在注册表项 HKCU\Environment 或值 Path 不存在的情况下处理 STDERR 输出的错误消息通过将其重定向到设备 NUL 来抑制2>nul。重定向运算符 > 必须在此处使用插入符号 ^ 转义,以便在 Windows 命令解释器解析 FOR 命令行时将其解释为文字字符,但在稍后执行 时作为重定向运算符REG 命令行在单独的后台命令进程中。

    使用 "skip=2 tokens=1,2*" 定义的 FOR 选项会导致跳过 REG 输出的前两行,并使用默认值将其他行分成三个子字符串(标记)分隔符空格和制表符。

    第一个空格/制表符分隔的字符串分配给第一个循环变量G,这是到达感兴趣数据行时的变量名称。

    作为注册表值类型的第二个子字符串被分配给循环变量H,它是ASCII table 中的下一个字符。这种行为是 FOR 循环变量区分大小写的原因。

    第二个子字符串之后的空格/制表符之后的所有内容都分配给循环变量I,而不会拆分行的其余部分,因为*tokens=1,2 之后的选项字符串中。

    因此,在 Windows Vista 和更高版本的 Windows 上,命令 FOR 作为 REG 输出的第一行处理 Path 行,而在 Windows XP 上处理第一行是注册表项的行,这就是第一个 IF 条件是必要的原因。

    第二个IF 条件进行不区分大小写的字符串比较,以找出名称为Path 的注册表值的类型。分配给Path 的字符串在REG_EXPAND_SZ 类型上包含一个或多个环境变量引用。出于这个原因,使用了命令call,这导致解析从注册表读取的字符串值,并由Windows命令处理器分配给循环变量I,以在命令SET之前展开所有环境变量引用> 执行后将展开后的字符串值赋给环境变量UserPath

    注意: cmd.exe 使用本地环境变量 PATHEXTPATH 搜索名称为 set 的可执行文件或脚本,因为使用了命令 CALL强>。命令 CALL 旨在从批处理文件中调用批处理文件,而不是强制 Windows 命令处理器再次解析命令行。

    仅当注册表值Path 不是REG_EXPAND_SZ 类型时才执行第三个IF 条件。它将不区分大小写的注册表值类型与字符串REG_SZ 进行比较,在这种情况下,Path 的字符串值可以直接分配给环境变量UserPath

    环境变量UserPathFOR 循环上方明确未定义。因此,如果当前行在任何情况下都具有第一个字符串Path,并且注册表值类型为REG_EXPAND_SZREG_SZ,那么现在应该定义环境变量UserPath,否则注册表值@987654385 @ 类型错误或带有空字符串。可以使用空字符串将Path 存储在 Windows 注册表中,但无法使用空字符串定义环境变量 UserPath

    第四个IF条件验证环境变量UserPath确实是用非空字符串定义的。在这种情况下,命令 GOTO 用于在成功地从 Windows 注册表中读取 user PATH 变量后退出 FOR 循环,方法是跳转到用于进一步处理环境变量UserPath的命令块。

    如果 user PATH 变量在 Windows 注册表中根本不存在,或者类型错误,或者存在,则到达 FOR 循环下方的命令块带有一个空字符串。

    为了完整的批处理代码

    • 从 Windows 注册表中读取 system AND user PATH,无需扩展,
    • 将两个PATH 变量连接到PATH,并在当前环境中的当前命令进程中覆盖local PATH
    • 如有必要,请立即展开所有环境变量引用。
    • PATH 值中的所有;; 替换为;
    • 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 /?

    另请阅读有关 Using Command Redirection Operators 的 Microsoft 文章,了解 2>nul 的解释,以及有关 Stack Overflow 主题 Single line with multiple commands using Windows batch file 的答案,了解命令行中运算符 & 的含义。

    【讨论】:

      【解决方案2】:

      echo %USERPROFILE%

      ...可能是 op 正在寻找的东西

      【讨论】:

        猜你喜欢
        • 2011-02-19
        • 1970-01-01
        • 2016-08-03
        • 1970-01-01
        • 2017-09-22
        • 1970-01-01
        • 2013-07-25
        • 1970-01-01
        相关资源
        最近更新 更多