How do I add to the Windows PATH variable using setx? Having weird problems
Asked Answered
S

13

112

I want to modify the Windows PATH variable using setx. The following works at least 50% of the time on Windows 8:

setx PATH %PATH%;C:\Python27\;C:\Python27\Scripts\

If it gives the error "the default argument can only be used 2 times", then the following works some of the time:

setx PATH "%PATH%;C:\Python27\;C:\Python27\Scripts\"

The difference is that we wrapped the second argument in quotes. I believe the quotes are necessary when %PATH% expands to include spaces.

However, I have encountered some weird problems on Windows 7. On one particular Windows 7 machine, I had this problem:

echo %PATH%

It prints:

C:\Foo\;C:\Bar\;[...lots of stuff...]C:\Baz\

Then I do this:

setx PATH "%PATH%;C:\Quux\"

Then it says "Error: Truncated at 1,024 characters." Now let's check what PATH contains:

echo %PATH%

It prints:

C:\Foo\;C:\Foo\;C:\Bar\;C:\Bar\;[...lots of stuff, now duplicated...]C:\B

...and it is cut off at 1,024 characters. It ran over because of the duplicates. Also interesting: The value of PATH changes despite the fact that setx raised an error and did not say "Success".

I was able to repeat this strange behavior several times (luckily I had saved the original contents of PATH).

At the moment, the only surefire way I know to append to the PATH is the following:

  1. echo the PATH.

  2. Copy the contents of PATH into a text file and manually add ;C:\Python27\;C:\Python27\Scripts\ to the end of the PATH.

  3. Copy the whole thing out of the text file.

  4. setx PATH "<paste the string here>"

That process works every single time on both Windows 7 and Windows 8.

I should really be able to do this in one command. What am I doing wrong?

Sewn answered 10/10, 2013 at 4:56 Comment(11)
This was a known problem on Vista, it should not occur on Win7. A corrupt copy of c:\windows\system32\setx.exe is the only simple explanation. Follow-up on superuser.com, this is not a programming question.Arboreal
Using setx is dangerous for another reason: if the path contains any environment variables, e.g., %JAVADIR%\bin, the reference will be lost, i.e., if JAVADIR changes the path will no longer change with it. If this is a software installer, it may break the end-users machines. Not a good idea.Longevity
Have you tried storing the "%PATH%;C:\Quux\" to a different (your own) variable and reference it in the SETX command line? As in SET "MyPath=%PATH%;C:\Quux\" SETX PATH "%MyPath%". Either way, since this appears to have to do with a known bug in a system tool, Super User may indeed be a better home for this question.Herriott
@HarryJohnston, This is by design. Whenever you do a %, it interprets it on the spot.Cresset
@Pacerier, any environment variable references in the registry entries for the path will already have been expanded, this happens as the environment block is built. So when you feed %PATH% into setx you are losing this information. Plus, of course, the way the OP is doing it the system path setting is getting added to the user path setting, looking at the question again it looks like that's the real cause of the OPs problem.Longevity
@HarryJohnston, There are 4 kinds of env variable: hkcu reg_sz, hkcu reg_expand_sz, hklm reg_sz, hklm reg_expand_sz. (You can manually tweak them with regedit and run setx to complete the flush.) ~~~ Both setx and setx/m defaults to reg_sz if your input contains 2+ % char. ~~~ "expand" in both hklm and hkcu mean expand to hklm. setx/m qwe %JAVADIR%\bin and setx/m javadir asdfg in either order. Then open a new cmd and do echo %qwe%: works as expected.Cresset
@Pacerier, I don't see the relevance. The value of PATH is already expanded as well as containing both the HKCU and HKLM entries (the latter is a special case, it doesn't happen for any other environment variable) so if the path in HKLM originally contained %JAVADIR%\bin and the path in HKCU originally contained %JDK%\bin then PATH will be set to C:\Java\bin;C:\jdk\bin so when you say setx PATH %PATH% the value in HKCU changes to C:\Java\bin;C:\jdk\bin which (a) contains a redundant entry and (b) no longer tracks changes to the value of JDK.Longevity
@Cresset Are you suggesting to use ~ surrounding variables? That doesn't seem to work to solve this problem.Allenaallenby
I don't know if this is completely relevant but i thought its be easier to do setx and did this > setx Path "C:\python\Scripts" and it didn't really append the new value instead it erased everything with only python there now. Did i use it right and I lost all the pre-existing values on thereDyanne
@HarryJohnston that is a good point on why setx is flawed, but what should we use instead? What is the good and safe way to update the path environment variable from the windows command line? Stack Overflow itself is littered with people recommending setx, outside of this one comment section.Chlorosis
@Brian, this looks promising, and could probably be turned into a one-liner for use inside a batch script.Longevity
D
95

Run cmd as administrator, then:

setx /M PATH "%PATH%;<your-new-path>"

The /M option sets the variable at SYSTEM scope. The default behaviour is to set it for the USER.

TL;DR

The truncation happens because when you echo %PATH% you get the concatenation of SYSTEM and USER values so, when you add it in your second argument to setx, the command will try to fit the contents of both SYSTEM and USER within the USER var. When you echo again, the result will be doubled.

The /M option requires administrator privilege, so you need to open your terminal with "run as administrator" otherwise setx will fail with "access to registry path is denied".

Note: You won't see the new value when you echo %PATH% just after setting it this way, you need to close cmd and open again.

If you want to check the actual values stored in registry check this question.

Doggo answered 15/11, 2014 at 15:2 Comment(5)
This solution is bogus. Executing the above command will change your Path type from REG_EXPAND_SZ to REG_SZ; and in the process, remove all environment variable references present there.Cereus
@garyM Thanks for the feedback. I didn't experience/notice the mentioned consequences in my case. Please let us know if there's a way to modify this answer that will fix it. Or if you suggest a different answer.Doggo
Hi Vituel,, The issue occurs when the variable is newly created then later modified within the same process. The newly created variable does not show up in the existing shell environment. any reference will treat the reference %var% as a text string. To avoid this issue, accessing the variable must be executed in a new process which created after the variable is created. The path variable is a special case on some version of windows. In 2008R2, modification of PATH variable is not promoted to existing processes, they need to be re-instantiated to get the changes. Based on OS, /M is at the end.Boxthorn
Also, this results in the user PATH variable being appended to the machine PATH, which will (a) interfere with other users; and (b) if run repeatedly, keep increasing the length of the path until it eventually overflows. Most of the time there won't be a user setting for PATH so you can get away with it, but it is dangerous.Longevity
DO NOT USE THIS. setx will truncate PATH to 1024 characters. If PATH was changed before by being prepended with more directories, you will lose most of the original PATH contents!Contreras
S
40

The PATH environment variable is constructed from a system-wide part and a user-specific part that are both stored in the registry.

Following commands make sure not to interfere with the system-wide part of PATH. Only the user-specific part is read, modified and written back to the registry.

for /f "usebackq tokens=2,*" %A in (`reg query HKCU\Environment /v PATH`) do set my_user_path=%B
setx PATH "C:\Python27;C:\Python27\Scripts;%my_user_path%"

The first command gets the user-specific part of PATH from the registry into a variable named my_user_path.

NOTE: Make sure the first command works without error

The second command prepends the C:\Python27;C:\Python27\Scripts; to the value of my_user_path and writes it back to the user-specific registry key for PATH.

NOTE: When used in a .bat file, replace % with %% in both places on the first line:

for /f "usebackq tokens=2,*" %%A in (`reg query HKCU\Environment /v PATH`) do set my_user_path=%%B

Only newly started programs will see the change in the PATH environment variable.

Shipmate answered 8/8, 2017 at 11:15 Comment(12)
this answer is logically correct imo. why did this answer neither get more votes nor was accepted ? Did I miss anything ?Suppuration
Coz stackoverflow (SO) is not taking the feedback :-) of it's users. If anyone talks about an answer being logical, this should be kind of pinnable answers like in Quora. Readers like you should be able to pin the good answers. SO is good, but not changing with the time, unfortunately. We can't even tag it like this, @stackoverflow , no one to listen.Shipmate
Should not the first line use double percentage signs instead of single percentage sign? I.e. %%A instead of %A and %%B instead of %B.Bigname
@Bigname - i think %% or % is to do with if you are running it as a .bat file or in the cmd directly. Hope that helps.Shipmate
Agree. This is the correct answer. As written, it is for running in a command prompt, and the single % must be replaced with double %% to run in a batch file.Analogical
@SOAdmins - i know this won't work :-) - Can you pin this answer? Multiple people agree that this is correct answer, but it is not pinned as a first answer :-)Shipmate
@ManoharReddyPoreddy Thanks, God saved me, though I had taken backups of environment variables, but this answer is a gem compared any other answer's. First store prev env vars and then append with new one. Works great :)Antoninus
@mozilla_firefox - yeah, we take backups then try something new :), we are proper devs? :DShipmate
I see in setx /? that it has a built in ability to read a registry value. Perhaps that will allow simplification by eliminating the extra for command.Townsville
@AmitNaidu Please provide, once you have new working answer. Thank you.Shipmate
First part is correct. Second part is not as it destroys user path.Vanna
not good: %SystemRoot%\system32;%SystemRoot%;C:\WINDOWS\system32;C:\WINDOWS;Asphyxia
T
8

If someone want to run it in PowerShell it works like below,

Run Powershell as Administrator

Then

setx /M PATH "$Env:PATH;<path to add>"

To verify, open another Powershell and view PATH as below,

$Env:PATH
Tadtada answered 11/10, 2017 at 3:21 Comment(0)
A
4

If you're not beholden to setx, you can use an alternate command line tool like pathed. There's a more comprehensive list of alternative PATH editors at https://superuser.com/questions/297947/is-there-a-convenient-way-to-edit-path-in-windows-7/655712#655712

You can also edit the registry value directly, which is what setx does. More in this answer.

It's weird that your %PATH% is getting truncated at 1024 characters. I thought setx didn't have that problem. Though you should probably clean up the invalid path entries.

Absorb answered 10/10, 2013 at 5:9 Comment(2)
Thanks for the suggestions, but I really do not want to rely on third-party software. I want to use only things that come with Windows. This is because I have two major use cases: (1) setting up newbies who want to learn Python, and (2) setting up machines that are used in my company's factory. In both cases, it is a random Windows machine that will only have the PATH edited once. I want to make the PATH edit as easy as possible, and installing more software really doesn't cut it. That's why even my 4-step workaround is not good enough.Sewn
So the tools I linked to have portable binaries that you can bundle in a zip file. You can have the users do something as simple as run a .bat file and have that handle PATH editing as well as setting up Python code.Absorb
A
4

Without admin rights the only way that worked for me is a bat file that contains the following code:

for /F "tokens=2* delims= " %%f IN ('reg query HKCU\Environment /v PATH ^| findstr /i path') do set OLD_SYSTEM_PATH=%%g
setx PATH "%USERPROFILE%\wev-tools;%OLD_SYSTEM_PATH%"

The code is the combination of the answers https://mcmap.net/q/13212/-how-do-i-add-to-the-windows-path-variable-using-setx-having-weird-problems and https://mcmap.net/q/13505/-how-to-persistently-set-a-variable-in-windows-7-from-a-batch-file

Ankeny answered 18/7, 2018 at 10:59 Comment(1)
if you want that part of the path to follow changes to %USERPROFILE%, you can use double %% in a bat file (or ^% if running the command directly - see how to escape in bat vs cmd).Allenaallenby
L
3

Sadly with OOTB tools, you cannot append either the system path or user path directly/easily. If you want to stick with OOTB tools, you have to query either the SYSTEM or USER path, save that value as a variable, then appends your additions and save it using setx. The two examples below show how to retrieve either, save them, and append your additions. Don't get mess with %PATH%, it is a concatenation of USER+SYSTEM, and will cause a lot of duplication in the result. You have to split them as shown below...

Append to System PATH

for /f "usebackq tokens=2,*" %A in (`reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH`) do set SYSPATH=%B

setx PATH "%SYSPATH%;C:\path1;C:\path2" /M

Append to User PATH

for /f "usebackq tokens=2,*" %A in (`reg query HKCU\Environment /v PATH`) do set userPATH=%B

setx PATH "%userPATH%;C:\path3;C:\path4"
Lucillelucina answered 2/1, 2020 at 23:6 Comment(2)
The only sensible answer here in 8 years. Except that the REG_EXPAND_SZ to REG_SZ issue and the 1024 character limit may still remain problems. Also look into setx /? because it can read the registry directly.Townsville
The only reason for wrapping it in a FOR loop was to put the results of the first command in a variable. Totally assbackward dos scripting, but that can't be helped. Didn't know setx could read those, so thanks for the addition.Lucillelucina
A
3

Just wanted to reiterate: the earlier answer from Manohar Reddy Poreddy is the correct one.

There are a number of improvements that can be made, that I thought might be helpful to share:

@echo off

REM -- Use directory where script is located. For current working directory, use %CD%
set CURRENT_DIR=%~dp0
REM -- Great example from Strawberry Perl's portable shell launcher:
if #%CURRENT_DIR:~-1%# == #\# set CURRENT_DIR=%CURRENT_DIR:~0,-1%

REM -- Load the user PATH from the registry, making sure it is not blank
reg query HKCU\Environment /v PATH 1>nul 2>&1
if ERRORLEVEL 1 goto skipLoadPath
for /f "usebackq tokens=2,*" %%A in (`reg query HKCU\Environment /v PATH`) do set MY_USER_PATH=%%B

REM -- Optionally, checks if this directory is already part of the user PATH
REM -- This will avoid duplication, and allow this to be run multiple times,
REM -- but if a sub-directory of the current is already part of the user PATH,
REM -- this script will simply not do anything
echo %MY_USER_PATH%|find "%CURRENT_DIR%" >nul
if errorlevel 1 (goto skipLoadPath) else (goto skipSetXPath)
:skipLoadPath

REM -- Avoid adding a useless semicolon to the previous user PATH
if not "" == "%MY_USER_PATH%" set "MY_USER_PATH=%MY_USER_PATH%;"
REM -- Permanently set the following location as part of the system path
setx PATH "%MY_USER_PATH%%CURRENT_DIR%" >nul 2>&1
REM -- This will update the current environment, since SETX only updates the registry
set "PATH=%PATH%;%MY_USER_PATH%%CURRENT_DIR%"
:skipSetXPath
Analogical answered 20/3, 2021 at 14:3 Comment(5)
For the part on finding a substring, I am indebted to this answer from MagooAnalogical
This should be the accepted answer IMHO, because it avoids duplicated paths. Minor suggestion: Consider using %1 instead of hard-coded "current directory" or any explicit policy. Leave the freedom to users.Phelloderm
... but then People From The Internet couldn't just script-kiddie this away .. might actually have to think about how it's being usedAnalogical
Well, I know you double-click it. Not being nit-picky, but I just turned it into a subroutine for my own usage. Thanks anyways.Phelloderm
It's cool. It is a good suggestion, it is an improvement, and I appreciate it. I dislike hard-coding as much as anyone, but in this context figured it's better to focus on the heart of the problem (duplicated paths, etc), instead of adding nice peripherals that may -- or may not -- give clarity to the central issue.Analogical
T
2

I was facing the same problems and found a easy solution now.

Using pathman.

pathman /as %M2%

Adds for example %M2% to the system path. Nothing more and nothing less. No more problems getting a mixture of user PATH and system PATH. No more hardly trying to get the correct values from registry...

Tried at Windows 10

Territorial answered 14/12, 2016 at 7:52 Comment(2)
pathman does the job flawlessly. Should be backwards compatible to Windows 2003 Resource KitKornher
@PatMigliaccio your link is deadAllenaallenby
A
2
setx path "%PATH%; C:\Program Files (x86)\Microsoft Office\root\Office16" /m

This should do the appending to the System Environment Variable Path without any extras added, and keeping the original intact without any loss of data. I have used this command to correct the issue that McAfee's Web Control does to Microsoft's Outlook desktop client.

The quotations are used in the path value because command line sees spaces as a delimiter, and will attempt to execute next value in the command line. The quotations override this behavior and handles everything inside the quotations as a string.

Amazed answered 2/7, 2020 at 14:21 Comment(0)
C
0

Steps: 1. Open a command prompt with administrator's rights.

Steps: 2. Run the command: setx /M PATH "path\to;%PATH%"

[Note: Be sure to alter the command so that path\to reflects the folder path from your root.]

Example : setx /M PATH "C:\Program Files;%PATH%"

Cyclostyle answered 29/5, 2017 at 16:12 Comment(1)
OP has decribed several details and observations for his problem. OP has described several attempts to solve his problem. Some of them are quite similar to your proposal. Can you highlight the relevant differences and explain how they solve OPs problem?Middleoftheroader
N
0

I was having such trouble managing my computer labs when the %PATH% environment variable approached 1024 characters that I wrote a Powershell script to fix it.

You can download the code here: https://gallery.technet.microsoft.com/scriptcenter/Edit-and-shorten-PATH-37ef3189

You can also use it as a simple way to safely add, remove and parse PATH entries. Enjoy.

Nowhither answered 20/11, 2017 at 2:46 Comment(0)
P
0

This vbscript/batch hybrid "append_sys_path.vbs" is not intuitive but works perfectly:

If CreateObject("WScript.Shell").Run("%ComSpec% /C ""NET FILE""", 0, True) <> 0 Then
    CreateObject("Shell.Application").ShellExecute WScript.FullName, """" & WScript.ScriptFullName & """", , "runas", 5
    WScript.Quit
End If
Set Shell = CreateObject("WScript.Shell")
Cmd = Shell.Exec("%ComSpec% /C ""REG QUERY ""HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"" /v Path | FINDSTR /I /C:""REG_SZ"" /C:""REG_EXPAND_SZ""""").StdOut.ReadAll
Cmd = """" & Trim(Replace(Mid(Cmd, InStr(1, Cmd, "_SZ", VBTextCompare) + 3), vbCrLf, ""))
If Right(Cmd, 1) <> ";" Then Cmd = Cmd & ";"
Cmd = "%ComSpec% /C ""REG ADD ""HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"" /v Path /t REG_EXPAND_SZ /d " & Replace(Cmd & "%SystemDrive%\Python27;%SystemDrive%\Python27\Scripts"" /f""", "%", """%""")
Shell.Run Cmd, 0, True

Advantages of this approach:

1) It doesn't truncate the system path environment at 1024 characters.
2) It doesn't concatenate the system and user path environment.
3) It's automatically run as administrator.
4) Preserve the percentages in the system path environment.
5) Supports spaces, parentheses and special characters.
6) Works on Windows 7 and above.

Polygamist answered 7/1, 2020 at 15:10 Comment(2)
Please add some comments to your code to explain what it does to the path strings; it looks like it is eliminating newlines. Why is the findstr necessary ? Does the /v path query return more than one line ? Don't name the variable holding the path value 'cmd'. It makes the already hard to read code even more obfuscated. And another simplified version for HKCU would be useful to folks who don't need to (or don't have the rights to) modify the system path.Townsville
Ok, now I see that those two cmd lines are just to remove extraneous findstr output. That can be done much more simply in a single command: for /F "skip=2 tokens=2*" %a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v path') do @set currpath=%b. Or better yet, don't use cmd. When in vbscript, use vbscript. Shell.RegRead("HKLM\SOFTWARE\etc"). Also see RegWrite.Townsville
J
0

Alternativelly, if you want to set the system path, here is a solution based on JonathanDavidArndt's answer.

@echo off
setlocal
chcp 65001 >nul
call :addToSystemPath C:\Program Files\Git\cmd
exit /b

:addToSystemPath
set ADDED_FOLDER=%*
REM -- Great example from Strawberry Perl's portable shell launcher:
if #%ADDED_FOLDER:~-1%# == #\# set ADDED_FOLDER=%ADDED_FOLDER:~0,-1%

REM -- Load the SYSTEM PATH from the registry, making sure it is not blank
SET PATH_ENV_HIVE=HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
reg query "%PATH_ENV_HIVE%" /v PATH 1>nul 2>&1
if ERRORLEVEL 1 goto skipLoadPath
for /f "usebackq tokens=2,*" %%A in (`reg query "%PATH_ENV_HIVE%" /v PATH`) do set SYSTEM_PATH=%%B
REM -- Optionally, checks if this directory is already part of the SYSTEM PATH
REM -- This will avoid duplication, and allow this to be run multiple times,
REM -- but if a sub-directory of the current is already part of the SYSTEM PATH,
REM -- this script will simply not do anything
echo %SYSTEM_PATH%|find "%ADDED_FOLDER%" >nul
if errorlevel 1 goto skipLoadPath
:skipSetXPath
echo Folder "%ADDED_FOLDER%" already in path
exit /b

:skipLoadPath
REM -- Avoid adding a useless semicolon to the previous SYSTEM PATH
if not "" == "%SYSTEM_PATH%" set "SYSTEM_PATH=%SYSTEM_PATH%;"
REM -- Permanently set the following location as part of the system path
setx /M PATH "%SYSTEM_PATH%%ADDED_FOLDER%"
rem >nul 2>&1
rem "On a local system, variables created or modified by this tool will be available in future command windows but not in the current CMD.exe command window."
REM -- This will update the current environment, since SETX only updates the registry
set "PATH=%PATH%;%ADDED_FOLDER%"
exit /b
Jewry answered 22/3 at 16:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.