编辑:经过一些测试,看起来我的原始答案并不完全适用于OP的问题。为了更直接地回答OP:
1.
%PATH%
将
HKLM\System\CurrentControlSet\Control\Session Manager\Environment\Path
中的值与
HKCU\Environment\Path
中的值结合起来。当你使用
setx "dir;dir"
时,你设置的是当前用户的
HKEY_CURRENT_USER Path
值。计算机范围内的
HKEY_LOCAL_MACHINE Path
值保持不变。这就是为什么你看到的值是附加的,而不是替换的。你必须使用
setx /m
来替换
HKLM Path
值。但是请不要这样做,除非你想在操作系统安装中创建严重的问题。
2. 如果你想测试
%PATH%
中是否存在目录,你可以
cd
或
pushd
至你想检查的目录和
%PATH%
中每个目录,以统一每个目录,确保所有相对路径、环境变量等都被展开。对于每个目录,使用
set "var=%CD%"
。然后使用
if /I "!dir1!"=="!dir2!"
来判断目录是否已经存在于
%PATH%
中。这在我的原始答案中有例子。
我的原始答案并不完全适用,因为
setx
本身并没有我曾经想象的那么破坏性。危险在于,通常情况下,当用户想将一个目录添加到他们的路径中时,他们会使用
setx /m PATH "%PATH%;new dir"
;而这是破坏性的。因为在
setx
写入值之前,
%PATH%
被展开,所有路径中的目录都被过早地展开了。
以下方法更安全:
set "env=HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
for /f "tokens=2*" %%I in (
'reg query "%env%" /v Path ^| findstr /i "\<Path\>"'
) do setx /m PATH "%%J;new directory"
但那并不是OP所问的,我对我那个莽撞的回答道歉。
原始回答:setx
是破坏性的,不应该这样使用。当你执行 setx PATH
时,你将注册表值数据类型从 REG_EXPAND_SZ 转换为 REG_SZ。一旦这样做,存储在你的 %PATH% 中的所有动态环境变量都会被转换为平面、绝对路径。使用 path
命令将目录暂时附加到你的 %PATH%
中,使用 reg add
永久地这样做。(顺便说一句,还有一个 dpath
,它可以将一个目录暂时添加到你的路径中,但只能被 type
命令使用。在这个页面的2/3位置滚动查看更多关于 dpath
的信息。)
这是我写的一个实用脚本,以一种不太具有破坏性的方式向我的 %PATH%
添加目录。它还将避免将相同的目录不管以何种方式格式化 (如尾随反斜杠、相对路径、环境变量或任何其他排列组合) 多次添加到 %PATH%
中。
@echo off
setlocal enabledelayedexpansion
if not exist "%~1" goto usage
for %%I in ("%~1") do pushd "%%~I" 2>NUL && (set "new=!CD!" && popd) || goto usage
for %%I in ("%PATH:;=";"%") do pushd "%%~I" 2>NUL && (
rem
if /i "!new!"=="!CD!" (
echo !new! already exists in %%PATH%%
goto :EOF
)
popd
)
call :append_path "%new%"
goto :EOF
:usage
echo Usage: %~nx0 "dir"
goto :EOF
:append_path <val>
set "env=HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
for /f "tokens=2*" %%I in ('reg query "%env%" /v Path ^| findstr /i "\<Path\>"') do (
rem
reg add "%env%" /f /v Path /t REG_EXPAND_SZ /d "%%J;%~1"
rem
for %%a in ("%%J;%~1") do path %%~a
)
rem
rem
(setx /m foo bar & reg delete "%env%" /f /v foo) >NUL 2>NUL
color 4E
echo Warning: %%PATH%% has changed. Reopen the console to inherit the changes.
goto :EOF
REG_EXPAND_SZ
更改为REG_SZ
?阅读了您的答案后,我想要为此任务调整我的批处理解决方案。但是,在使用文件版本6.1.7600.16385的__setx__在Windows 7 SP1 x64上执行批处理代码之前和之后,先查看注册表值Path
的类型,但每次修改后,注册表值的类型都没有更改为REG_EXPAND_SZ
。我可以在Process Monitor中看到__setx__首先查询Path
,然后以正确的类型设置它。 - MofiHKLM\System\CurrentControlSet\Control\Session Manager\Environment
并创建一个新的REG_EXPAND_SZ
值,将其命名为 "foo" 并将其数据设置为 "bar"。保持该窗口打开,但打开一个控制台窗口并执行setx /m foo bar
。现在返回注册表编辑器窗口并刷新。foo
现在是类型REG_SZ
。但我发现如果我执行setx /m foo %bar%
(其中%bar%
未定义),setx 将数据类型设置回REG_EXPAND_SZ
。我忘记在哪里读到了setx
的破坏性质,但直到现在我才真正进行了实验。 - rojosetx
添加目录时,%PATH%
中的所有变量都保持折叠。 - rojo%...%
,则使用REG_EXPAND_SZ
,否则类型为REG_SZ
。 - Mofi