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

查看:21
本文介绍了如何在 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 "....liblibsndfile;....libsimulink" 
@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

....liblibsndfile;....libsimulink

问题 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%HKLMSystemCurrentControlSetControlSession ManagerEnvironmentPath 中的值与 HKCUEnvironmentPath 合并.当您 setx "dir;dir" 时,您设置的是 HKEY_CURRENT_USER Path 值.机器范围的 HKEY_LOCAL_MACHINE Path 值保持不变.这就是为什么您将值视为附加值而不是替换值的原因.您必须使用 setx/m 来替换 HKLM Path 值.但是除非您想在操作系统安装中造成严重问题,否则请不要这样做.

  1. %PATH% combines the values in HKLMSystemCurrentControlSetControlSession ManagerEnvironmentPath with HKCUEnvironmentPath. 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% 中的每个目录以统一每个目录,确保所有相对路径、环境变量等都被扁平化.为每个设置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=HKLMSystemCurrentControlSetControlSession ManagerEnvironment"

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此页面,了解有关 dpath 的更多信息.)

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=HKLMSystemCurrentControlSetControlSession ManagerEnvironment"
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天全站免登陆