90

I am trying to set environment variables using the setx command, such as follows

setx PATH "f:\common tools\git\bin;f:\common tools\python\app;f:\common tools\python\app\scripts;f:\common tools\ruby\bin;f:\masm32\bin;F:\Borland\BCC55\Bin;%PATH%"

However, I get the following error if the value is more then 1024 characters long:

WARNING: The data being saved is truncated to 1024 characters.

SUCCESS: Specified value was saved.

But some of the paths in the end are not saved in variable, I guess due to character limit as the error suggests.

8
  • There's a list of alternative ways to edit the %PATH% at superuser.com/questions/297947 Oct 10, 2013 at 5:15
  • 1
    Look into Rapid Environment Editor which allows you to edit all envirnoment variables graphically (you can also save a backup also). Dec 17, 2016 at 19:46
  • 3
    Is anyone else bother by this claiming success when it clearly does not do what was requested? Is it not troubling that this doesn't fail while leaving the path exactly how it was? Jul 17, 2017 at 16:00
  • 3
    Yes, it does on Windows 10
    – Ivan
    Mar 23, 2018 at 0:26
  • 1
    it still does on windows 1909
    – dkocich
    Apr 15, 2020 at 20:21

11 Answers 11

59

Your best bet is to edit the registry directly.

Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment and edit the Path value (then reboot to activate the new value).

Note however that while you can enter a very long path, (up to the maximum environment variable length; 2,048 or 32,768 bytes depending on the source), not all software will be able to read and handle it correctly if it is too long.

16
  • 2
    Is reboot really required here ? How does setx do it ? Setx does not require reboot. Feb 9, 2012 at 14:10
  • 12
    Yes, a reboot is required. setx edits the registry as I indicated, then broadcasts a WM_SETTINGCHANGE message. This tells all top-level windows that a system setting has changed (in this case an environment variable). Without that, Explorer and programs you opened with it will not know about the change. You could broadcast the message yourself manually (I wrote a program to do just that, and a batch file to replace SETX that makes a registry edit followed by the broadcast), but just like setx and the System Properties envvar dialog, it has side-effects that make rebooting preferable.
    – Synetech
    Feb 9, 2012 at 19:05
  • 2
    Oh and editing an env.var. actually causes problems if you don’t reboot because any environment variables that contain other variables will stop being expanded. For example, I just broadcast it and now this is my path and I get an error because the path is now “broken”/empty. None of the vars will expand properly again until I reboot. Unfortunately this is “normal”. :-|
    – Synetech
    Feb 10, 2012 at 3:40
  • 3
    I found a small PowerShell script that will broadcast the WM_SETTINGCHANGE message. Apr 7, 2012 at 23:13
  • 13
    You can use the above registry method via the REG add command and then use SETX to set some other variable to itself (ie: SETX /M USERNAME %USERNAME%). This will cause the WM_SETTINGCHANGE message to be set and give your the ability to set the path from a batch file.
    – Art
    Sep 14, 2012 at 2:26
37

if you are using windows vista or higher, you can make a symbolic link to the folder. for example:

mklink /d C:\pf "C:\Program Files"
mklink /d C:\pf86 "C:\Program Files (x86)"

would make a link so c:\pf would be your program files folder. I shaved off 300 characters from my path by using this trick.

(I know it's not related to setx but it is useful for people which are searching overcomming on 1024 char limit)

4
  • Useful when you are an administrator. For the rest of us: You do not have sufficient privilege to perform this operation. In a pinch,subst can do something similar.
    – Amit Naidu
    Mar 11, 2021 at 23:43
  • Think about it, it's not the most optimal solution. Even if you symblink Windows and system32 folders you will eventually run out of 1024 char limit. What is much smarter is to add some folder like C:\slnk in the PATH variable and then create symbolic links to all the programs/files you want to launch from path in that folder! This way, you will never, ever run out of PATH, even after adding thousands of programs! @AmitNaidu you can also do this with hard links instead of symbolic links, hard links does not require administrative privileges! Jul 20 at 17:21
  • Also, symbolic links in path variable might make some programs exert undefined behaviour, I suspect. Jul 20 at 17:22
  • I allocated probably too much effort to created a tool that solves this problem decisively. Details are in the readme. Jul 24 at 17:52
27

You could use a PowerShell script similar to the following:

$newPath = 'F:\common tools\git\bin;F:\common tools\python\app;F:\common tools\python\app\scripts;F:\common tools\ruby\bin;F:\masm32\bin;F:\Borland\BCC55\Bin'
$oldPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine');
[Environment]::SetEnvironmentVariable('PATH', "$newPath;$oldPath",'Machine');

The Environment.SetEnvironmentVariable() API call will broadcast WM_SETTINGCHANGE so you do not need to reboot.

4
  • Don't you also need the following line: [Environment]::SetEnvironmentVariable('path', "$newPath",'Machine'); Aug 28, 2013 at 13:21
  • 1
    In the 3rd line, I'm not sure what benefit the extra dollar signs and parentheses bring. Couldn't you just say [Environment]::SetEnvironmentVariable('path', "$newPath;$oldPath",'Machine') ? Jan 15, 2015 at 19:21
  • 1
    @twasbrillig I'm just careful when I'm including a variable in a string. in this case its unecessary. Jan 15, 2015 at 20:46
  • 4
    You can call this from an Administrator Command Prompt: @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -Command "[Environment]::SetEnvironmentVariable('path',\"C:\Program Files (x86)\GNU\GnuPG;$([Environment]::GetEnvironmentVariable('path','Machine'))\",'Machine');"
    – Mark C
    Jul 18, 2017 at 19:14
7

This open-source SetEnv command-line tool is good to edit the PATH and other environment variables without limitations. It uses a dynamic buffer so no static limitations like 1024.

http://www.codeproject.com/Articles/12153/SetEnv

The choice of a % as a prefix to append to a variable could have been better though, as makes the syntax difficult sometimes if used with other batch local variables...

1
  • > SetEnv tool is good to edit the PATH and other environment variables without limitations Indeed. In fact, I had personally worked with Darka on that page to help make SetEnv even better so that it can fully support expanding/sub-variables (the Dynamic Variable Expansion section), which actually helps to reduce the length of the raw path.
    – Synetech
    Jun 28, 2012 at 5:39
4

A far superior tool than setx for path manipulation is pathed.exe. Unfortunately, it's limited to editing the path.

In addition to a superior user experience than setx, you don't have a 1024 character limit. Unlike direct registry manipulation, this application uses the Environment.SetEnvironmentVariable() API call which will broadcast WM_SETTINGCHANGE.

2
3

You can put this line in your BAT:

setx path "%%path%%;c:\drive\fr;c:\drive\installs\7z"

See the double %%.

(Reference: https://support.microsoft.com/en-us/kb/75634)

3
  • 1
    Link is now broken
    – Ivan
    Mar 23, 2018 at 0:29
  • 3
    WARNING! This possibly will break things, it will write %path%;c:\...[snip]...\7z to the user path variable, dropping anything else you had there. May 31, 2018 at 22:53
  • The PATH environment variable used by programs is a combination of the machine and local PATH variables. In addition to destroying the current data in the local path I don't think this does anything. Having %path% in the local path environment variable should have no effect.
    – AnnanFay
    Mar 14, 2019 at 13:30
2

My favorite way is to change the folder names in the PATH variables to use the 8.3 names. This StackOverflow answer has an awesome script (run from a .bat file) that will generate the "minified" version of the entire PATH variable, which you can then paste into the Edit Variable dialog(s). Only caveat is that you will need to split out the SYSTEM and USER parts. As the script goes through and figures out the minified version for each folder, it discards and alerts you of any invalid/non-existent paths. Nice little clean up bonus.

5
  • 2
    Be careful if you have used fsutil.exe behavior set disable8dot3 1. Jan 6, 2016 at 19:04
  • @AndrewMorton good point but wouldn't that be "handled" by the fact that the script doesn't "generate" the 8.3 name, it just reports the 8.3 name that the file system assigned? So if a folder did not have an 8.3 name, the script would not propose a substitute. However, using fsutil 8dot3name strip AFTER using the script would definitely cause problems for affected folders. Jan 13, 2016 at 18:55
  • Unfortunately I don't have a spare drive or system to check it on. However, having used some fsutil 8dot3name strip earlier today and considering that (a) it checks the registry first and (b) the path is stored in the registry, my earlier concern may be unwarranted, as long as the user does not use the /f (force) option. Jan 13, 2016 at 19:05
  • This solution is not very good, as no matter how much you shorten PATH paths, you will eventually run out of 1024 characters. Jul 21 at 11:09
  • And you are entitled to that opinion. I never said this was the BEST way to do it, just that it is MY favorite way (and I have never had problems with it). If you use this method and still hit the 1024 limit you may want to rethink everything installed on your machine and/or any paths you may have added manually. Some of the other ways here are much more "invasive" and one even mentions that some software may not work with it. That is what is so awesome with having choices, you can choose which one suits your fancy. Jul 29 at 17:38
1

A new tool is born, it works very well, have unique features and solve all setx problems: regenv

  • it works in xp+.

  • it is better than setx ,pathed, pathman, setenv

  • it is a fork of the old nice setenv tool

set "var=D:\Bin"

REM ::::: override a system var:
regenv.exe set -nS c "%var%"

REM ::::: append to a system var
regenv.exe set -nS -sa c "%var%"

REM ::::: preppend to a system var
regenv.exe set -nS -sp c "%var%"

REM ::::: create a variable that contains an unexpanded variable
regenv.exe set -nS -sp c "%%var%%"

REM ::::: edit PATH: if you edit PATH it is good to use -x , because -x will convert the reg type from REG_SZ to REG_EXPAND_SZ, because some tools may create a REG_SZ while the default reg type for PATH is/should be REG_EXPAND_SZ
regenv.exe set -nS -sp -x PATH "%var%"

NB: if var contain a backslash at the end, use double backlash:

regenv.exe set -nS c "D:\Bin\\"
REM gaves D:\Bin\

or delete the last backslash:

set "var=D:\Bin\"
REM -- Great example from Strawberry Perl's portable shell launcher:  this deletes the final backslash \.
if #%var:~-1%# == #\# set var=%var:~0,-1%
regenv.exe set -nS c "%var%"
:: gaves D:\Bin

it can even create Volatile variables (HKCU\Volatile Environment).

it is really a nice work.

0

I think the best way is the next (with powershell) With this way also you avoid the litmit of 1024 character.

You can see the code on: https://gist.github.com/drazul/b92f780689bd89a0d2a7

#------------ Add path to system variable -------------------------------------

$path2add = ';C:\path;'
$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

If (!$systemPath.contains($path2add)) {
    $systemPath += $path2add
    $systemPath = $systemPath -join ';'
    [Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');
    write-host "Added to path!"
    write-host $systemPath
}

#------------ Delete path from system variable --------------------------------

$path2delete = 'C:\path;'
$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

$systemPath = $systemPath.replace($path2delete, '')
$systemPath = $systemPath -join ';'

[Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');

write-host "Deleted from path!"
write-host $systemPath

#------------ Clean system variable -------------------------------------------

$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

while ($systemPath.contains(';;')) {
    $systemPath = $systemPath.replace(';;', ';')
}

[Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');

write-host "Cleaned path!"
write-host $systemPath
-1

if it is not required to keep system PATH and user PATH separate:

::setx /m truncate variable length to 1024 REG ADD 
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH /t REG_SZ /f /d "%PATH%"
::empty local path, use system wide only, else it will enlarge with every setx /m
setx PATH ""
::setx is dummy but propagate system wide variables with it
setx /m A A
3
  • 1
    Can you explain a bit more about what you are suggesting here? Oct 24, 2014 at 14:18
  • It is just a ready to use command to workaround setx 1024 character limit. Example is shown directly on PATH variable. Although the previous answers are helpful they lack a final solution.
    – Fantastory
    Oct 24, 2014 at 16:16
  • System path and user path are separate for a reason. This combines them and puts everything in the system path. That is a major change to the environment behavior and is not expected by a user who is just looking to add something to their user path variable.
    – Amit Naidu
    Mar 11, 2021 at 23:53
-1

Just a little ready-to-use packing of the Powershell version . Save this as a .cmd or .bat, UTF-8 or ASCII text file . Remember to restart programs that were running during the change .

@echo off
set br=^


rem br;
pushd "%~dp0"       &rem Working/{temp files} Directory . pat>->paf ;
setlocal enableExtensions enableDelayedExpansion


rem # Required :
rem Windows Powershell v1.0 by Microsoft .
rem # ;


echo Make sure to run this as Administrator .!br!
pause
echo(
set v=

set /p v=Enter the items to add . Separate by, and end the list with ";" . Do not use quotes .!br!!br!&     rem #optional

rem set v=C:\Windows\WinSxS;!v!     &rem MSBuild ; #optional

"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -Command "[Environment]::SetEnvironmentVariable('Path',\"%v%$([Environment]::GetEnvironmentVariable('Path','Machine'))\",'Machine');"      &rem Windows Powershell by Microsoft ;


:sc_n
rem endlocal
rem popd
pause
rem exit /b

Not the answer you're looking for? Browse other questions tagged or ask your own question.