我有批处理文件,用于设置用户路径,并作为Visual Studio IDE构建步骤的一部分运行.
@ECHO OFF
@ECHO %PATH%
set COMSPEC = "%VCINSTALLDIR%\vcvarsall.bat" amd64
setx PATH "..\..\lib\libsndfile;..\..\lib\simulink"
@ECHO %PATH%
Run Code Online (Sandbox Code Playgroud)
当我构建项目,关闭VS,并重新打开它,并重建时,我将附加路径视为PATH
变量的一部分.但是,我看到在Windows环境中设置环境变量PATH
变量是在用户环境变量下创建的
..\..\lib\libsndfile;..\..\lib\simulink
Run Code Online (Sandbox Code Playgroud)
问题1:
为什么此路径也作为附加路径显示为系统环境变量的一部分?
在echo %PATH%
通过Visual Studio控制台执行时(当我第二次运行项目时)打印系统变量路径和我创建的新路径附加到它.
问题2:
我想修改我的批处理文件,以便它只PATH
在首次运行Visual Studio构建期间在用户设置中设置一次环境变量.如果用户变量PATH
在后续运行中已存在,则不应再次执行set命令以避免在系统变量中反复添加新路径.
任何想法如何实现这一目标?
编辑:经过一些测试,我的原始答案似乎并不完全适用于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%
以统一每个目录,确保所有相对路径,环境变量等都是平坦的. 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"
Run Code Online (Sandbox Code Playgroud)
但这并不是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 // 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
Run Code Online (Sandbox Code Playgroud)