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.ba
That what Setx does. See Setx /?
where it tells you this. It adds it to the user's environment permanently (unless /m is used). However %PATH% is built from system and user environment's PATH (and also autoexec.bat on 32 bit windows and if started through ShellExecute also App Paths reg key))
Don't worry about. Setx doesn't add paths to %PATH% if they already exist in %PATH%.
Why are you redefining the system variable %COMSPEC%.
edit: After some testing, it appears that my original answer isn't entirely applicable to OP's questions. To answer OP more directly:
%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.
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.
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.
The following method would be safer:
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"
But that wasn't really what OP asked, and I apologize for the knee-jerk answer.
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
.)
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