如何在Windows上仅在批处理文件中设置PATH环境变量一次? [英] How to set PATH environment variable in batch file only once on Windows?

查看:133
本文介绍了如何在Windows上仅在批处理文件中设置PATH环境变量一次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个设置用户路径的批处理文件,它是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:

  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值. 但是请不要这样做,除非您想在操作系统安装过程中遇到严重的问题.

  1. %PATH% combines the values in HKLM\System\CurrentControlSet\Control\Session Manager\Environment\Path with HKCU\Environment\Path. When you setx "dir;dir", what you're setting is the HKEY_CURRENT_USER Path value. The machine-wide HKEY_LOCAL_MACHINE Path value remains untouched. That's why you see your values as appended, rather than as replacements. You'd have to use setx /m to replace the HKLM Path value. But please don't unless you want to create severe problems with your operating system installation.

如果要测试%PATH%中是否存在目录,可以同时cdpushd到要检查的目录以及%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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆