如何在Windows上仅在批处理文件中设置PATH环境变量一次? [英] How to set PATH environment variable in batch file only once on Windows?
问题描述
我有一个设置用户路径的批处理文件,它是Visual Studio IDE生成步骤的一部分.
I have batch file that sets user path and is run as part of Visual Studio IDE build step.
@ECHO OFF
@ECHO %PATH%
set COMSPEC = "%VCINSTALLDIR%\vcvarsall.bat" amd64
setx PATH "..\..\lib\libsndfile;..\..\lib\simulink"
@ECHO %PATH%
当我构建项目时,关闭VS,然后重新打开它,然后重新构建,我看到了
追加的路径作为PATH
变量的一部分.但是,我看到在Windows中环境变量PATH
的设置是在用户环境变量下创建的,
When I build the project, close VS, and reopen it, and rebuild, I see
appended path as part of PATH
variable. However, I see that in Windows setting of environment variable PATH
variable is created under user environment variables as
..\..\lib\libsndfile;..\..\lib\simulink
问题1:
为什么此路径也作为附加路径显示为系统环境变量的一部分?
Why does this path also appear as appended path as part of system environment variable?
在通过Visual Studio控制台执行echo %PATH%
时(当我第二次运行项目时)会打印系统变量路径以及我创建的新路径.
On executing echo %PATH%
through Visual Studio console (when I run the project second times) prints system variable path and the new path I created appended to it.
问题2:
我想修改我的批处理文件,以便它在第一次运行Visual Studio构建期间仅在用户设置中设置一次PATH
环境变量.如果用户变量PATH
在后续运行中已经存在,则不应再次执行 set 命令,以避免在系统变量中一次又一次地添加新路径.
I want to modify my batch file so that it only sets once PATH
environment variable in user settings during first run of Visual Studio build. If the user variable PATH
already exists on subsequent runs, it should not execute set command again to avoid appending new path again and again in system variable.
有什么想法可以实现这一目标吗?
Any ideas how to achieve this?
推荐答案
经过一些测试,看来我的原始答案并不完全适用于OP的问题.要更直接地回答OP:
edit: After some testing, it appears that my original answer isn't entirely applicable to OP's questions. To answer OP more directly:
-
%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%
combines the values inHKLM\System\CurrentControlSet\Control\Session Manager\Environment\Path
withHKCU\Environment\Path
. When yousetx "dir;dir"
, what you're setting is theHKEY_CURRENT_USER
Path
value. The machine-wideHKEY_LOCAL_MACHINE
Path
value remains untouched. That's why you see your values as appended, rather than as replacements. You'd have to usesetx /m
to replace theHKLM
Path
value. But please don't unless you want to create severe problems with your operating system installation.
如果要测试%PATH%
中是否存在目录,可以同时cd
或pushd
到要检查的目录以及%PATH%
中的每个目录以统一每个目录,从而确保所有相对路径,环境变量等被展平.每个set "var=%CD%"
.然后if /I "!dir1!"=="!dir2!"
目录已经在%PATH%
中的某个位置存在.在下面的原始答案中有一个示例.
If you want to test whether a directory exists in %PATH%
, you could cd
or pushd
both to the directory you want to check and to each directory within %PATH%
to unify each, making sure all relative paths, environment variables, etc. are flattened. set "var=%CD%"
for each. Then if /I "!dir1!"=="!dir2!"
the directory already exists somewhere in %PATH%
. There's an example of this in my original answer below.
我的原始答案不能完全适用的原因是,setx
本身并不像我曾经想象的那样具有破坏性.危险在于,当用户通常希望将目录添加到其路径时,他们会setx /m PATH "%PATH%;new dir"
;而且 具有破坏性.因为%PATH%
在setx
写入值之前被扩展,所以PATH中的所有目录都被过早扩展.
The reason my original answer isn't entirely applicable is because setx
itself isn't as destructive as I once thought. The danger is that often times when users want to append a directory to their path, they'll setx /m PATH "%PATH%;new dir"
; and that is destructive. Because %PATH%
is expanded before setx
writes the value, all the directories in PATH are expanded prematurely.
以下方法会更安全:
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真正要求的,我为下意识的回答道歉.
But that wasn't really what OP asked, and I apologize for the knee-jerk answer.
原始答案:setx
具有破坏性,不应以这种方式使用. setx PATH
时,您正在将注册表值数据类型从REG_EXPAND_SZ转换为REG_SZ.一旦执行此操作,存储在%PATH%中的所有动态环境变量都将转换为平坦的绝对路径.使用path
命令将目录临时添加到%PATH%
,并使用reg add
永久添加目录. (作为附带说明,还有dpath
,它会临时将目录添加到您的路径,但只能由type
命令使用.向下滚动2/3到
original answer: setx
is destructive and shouldn't be used this way. When you setx PATH
you're converting the registry value data type from REG_EXPAND_SZ to REG_SZ. As soon as you do this, all the dynamic environment variables stored in your %PATH% get converted to flat, absolute paths. Use the path
command to append directories to your %PATH%
temporarily, and reg add
to do so permanently. (As a side note, there's also dpath
, which temporarily adds a directory to your path, but can only be used by the type
command. Scroll 2/3 the way down this page for more info on dpath
.)
这是我编写的实用程序脚本,用于以较小破坏性的方式将目录添加到我的%PATH%
.不论其格式如何(例如,尾随反斜杠,相对路径,环境变量或任何其他排列方式),它都将避免将同一目录多次添加到%PATH%
.
Here's a utility script I wrote to add directories to my %PATH%
in a less destructive manner. It will also avoid adding the same directory to %PATH%
more than once, regardless of how it's formatted (e.g. trailing backslash, relative paths, environment variables, or any other permutation).
@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
这篇关于如何在Windows上仅在批处理文件中设置PATH环境变量一次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!