我有批处理文件,用于设置用户路径,并作为Visual Studio IDE构建步骤的一部分运行。
@ECHO OFF
@ECHO %PATH%
set COMSPEC = "%VCINSTALLDIR%\vcvarsall.bat" amd64
setx PATH "..\..\lib\libsndfile;..\..\lib\simulink"
@ECHO %PATH%
当我构建项目时,关闭VS,重新打开它,然后重建,我明白了
附加路径作为PATH
变量的一部分。但是,我发现在Windows环境变量PATH
变量中,变量是在用户环境变量下创建的
..\..\lib\libsndfile;..\..\lib\simulink
问题1:
为什么此路径也作为附加路径显示为系统环境变量的一部分?
在通过Visual Studio控制台执行echo %PATH%
时(当我第二次运行项目时)打印系统变量路径和我创建的新路径。
问题2:
我想修改我的批处理文件,以便在首次运行Visual Studio构建期间只在用户设置中设置一次PATH
环境变量。如果后续运行中已存在用户变量PATH
,则不应再次执行 set 命令以避免在系统变量中反复添加新路径。
任何想法如何实现这一目标?
答案 0 :(得分:6)
编辑经过一些测试后,我的原始答案似乎并不完全适用于OP的问题。更直接地回答OP:
%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
值。 但除非您想在操作系统安装中出现严重问题,否则请不要这样做。
如果您想测试%PATH%
中是否存在目录,您可以cd
或pushd
同时查看要检查的目录以及%PATH%
内的每个目录1}}统一每个,确保所有相对路径,环境变量等都是平坦的。每个set "var=%CD%"
。然后if /I "!dir1!"=="!dir2!"
目录已存在于%PATH%
中的某个位置。我的原始答案中有一个例子。
我的原始答案不完全适用的原因是因为setx
本身并不像我曾经想象的那样具有破坏性。危险在于,当用户想要将目录附加到他们的路径时,他们会setx /m PATH "%PATH%;new dir"
;并且 具有破坏性。因为%PATH%
在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向下this page有关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 // delaying expansion of !new! prevents parentheses from breaking things
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 // make addition persistent through reboots
reg add "%env%" /f /v Path /t REG_EXPAND_SZ /d "%%J;%~1"
rem // apply change to the current process
for %%a in ("%%J;%~1") do path %%~a
)
rem // use setx to set a temporary throwaway value to trigger a WM_SETTINGCHANGE
rem // applies change to new console windows without requiring a reboot
(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
答案 1 :(得分:1)
这就是Setx所做的。请参阅Setx /?
,告诉您这一点。它将其永久地添加到用户的环境中(除非使用/ m)。但是%PATH%是根据系统和用户环境的PATH构建的(在32位窗口上也是autoexec.bat,如果通过ShellExecute启动,也是App Paths reg键))
不要担心。如果%PATH%中已存在路径,则Setx不会将路径添加到%PATH%。
为什么要重新定义系统变量%COMSPEC%。