250

Windows has the setx command:

Description:
    Creates or modifies environment variables in the user or system
    environment.

So you can set a variable like this:

setx FOOBAR 1

And you can clear the value like this:

setx FOOBAR ""

However, the variable does not get removed. It stays in the registry:

foobar

So how would you actually remove the variable?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 7
    setx just sets the variable. You're just blanking it with that line. – tew Nov 04 '12 at 23:43
  • 1
    see also http://stackoverflow.com/questions/1472722/how-to-remove-system-environment-variable-by-using-batch-file – Brian Burns Mar 03 '14 at 17:27
  • Since it took me a fair amount of digging, also see http://superuser.com/q/297947/46834 for non-command line options. – gary Dec 29 '16 at 16:30

11 Answers11

310

To remove the variable from the current environment (not permanently):

set FOOBAR=

To permanently remove the variable from the user environment (which is the default place setx puts it):

REG delete HKCU\Environment /F /V FOOBAR

If the variable is set in the system environment (e.g. if you originally set it with setx /M), as an administrator run:

REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR

Note: The REG commands above won't affect any existing processes (and some new processes that are forked from existing processes), so if it's important for the change to take effect immediately, the easiest and surest thing to do is log out and back in or reboot. If this isn't an option or you want to dig deeper, some of the other answers here have some great suggestions that may suit your use case.

CupawnTae
  • 14,192
  • 3
  • 29
  • 60
  • 3
    This solution doesn't seem to work - or I'm misunderstanding something basic. I do `setx JUNK Hello`. Open new cmd. Type `echo %JUNK%` and get `Hello`. Then I do `REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNK`, and confirm that value is gone from registry. I open new cmd and type `echo %JUNK%` and still get `Hello`. Search of registry show no presence of 'JUNK'. Please don't tell me you need a reboot! – caasjj Apr 05 '16 at 16:42
  • 1
    Thanks for the reply. I am opening a new command window from the Start menu. I have tried both versions of the command. In fact, the first time when I type the `user` environment command, it succeeds. Then, when I retype the command I get `The system was unable to find the specified registry or key value`. Also, a global search for `JUNK` in the registry with `regedit` turns up nothing. Still, when I open up a new Command window (via Start/accessories, or cmd.exe in Run) and type `echo %JUNK%`, the value is still there! – caasjj Apr 05 '16 at 18:02
  • Yep, tried that already. If I reboot then the value disappears, but only if I reboot. Nothing else seems to work (32-bit Win7 Pro SP1)?! Thanks for you help, though. – caasjj Apr 05 '16 at 19:31
  • 1
    Ah! What do you suppose the rational is for that?? I always avoid admin as much as possible - UNIX/BSD/Linux upbringing. Thanks a mil for the awesome diligence. +1 – caasjj Apr 05 '16 at 20:36
  • Yep. I guess that implies that in order for the deletion to take effect, you basically need to logout and back in. – caasjj Apr 05 '16 at 22:23
  • 6
    maybe it's just semantics, but the deletion (from the registry) takes effect immediately. The environment is not re-initialized from the registry until you log in again. You can combine the 2 commands to remove it from the current environment (which will remove it from the `SET` list for the next cmd shell) and then remove it from the registry, e.g.: `SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR` – Luke Aug 04 '17 at 17:02
  • 1
    The reason the environment doesn't seem to get updated without rebooting is because explorer.exe doesn't know that it's been updated. See my answer for full explanation and solution. – Jamie Feb 15 '18 at 21:12
  • Don't you allways trust them with high reputation! setx variablename "" does delete the variable (at least on Windows Server 2019). – Christian4145 Mar 03 '22 at 16:11
  • It doesn't delete it from the registry, it leaves it there with a blank value, hence the original question - are you looking in the registry as per the screenshot? Tested just now on Windows 10 Pro 21H2, still there. – CupawnTae Mar 03 '22 at 20:16
68

To remove the variable from the current command session without removing it permanently, use the regular built-in set command - just put nothing after the equals sign:

set FOOBAR=

To confirm, run set with no arguments and check the current environment. The variable should be missing from the list entirely.

Note: this will only remove the variable from the current environment - it will not persist the change to the registry. When a new command process is started, the variable will be back.

Luke
  • 418
  • 4
  • 11
Brian Kelly
  • 1,081
  • 7
  • 2
  • 100
    This is definitely NOT the answer, and I find it disturbing that there are so many up-votes. This is only effective for the current command session. Crank up a new command window, and the var is back. – joescii Apr 25 '14 at 15:41
  • 6
    @joescii You find this surprising? This answered the question in the question title. So obviously the question title needed to be more specific. – oberlies May 15 '14 at 14:25
  • 12
    @oberlies I disagree that it answers the question in the title, because this does NOT work at the OS-level, but only in the current command window. Secondly, your point suggests that the details portion of the question are irrelevant. – joescii May 15 '14 at 17:26
  • @joescii That's good that you disagree. Because this means that my edit made it specific enough :-) – oberlies May 15 '14 at 17:37
  • 4
    @oberlies unfortunately the edit doesn't seem to have done the trick - it's still getting upvotes. I guess people find it useful even if it doesn't answer the actual question, in which case maybe it deserves the upvotes (does it?). At least it's not marked as accepted, which would be misleading. – CupawnTae Jan 22 '15 at 14:00
  • @CupawnTae Go for it. – chappjc Feb 10 '15 at 01:04
  • 4
    I'm supposed to comment why I downvoted. Obviously because this only works in the current session. – Ian Grainger Feb 10 '16 at 09:54
  • 2
    I arrived here looking for a way to only unset it in the current session - so this answer provided exactly what I was looking for. As long as the answer is related to the question and clearly defines it's limitations, why downvote? – Luke Dec 23 '16 at 16:33
  • 1
    This is the answer I was looking for, the note also makes it clear enough so I don't think it matters that it does not answer the main question. – Arijoon Apr 03 '17 at 09:39
  • Thank you loads this saved my npm http_proxy issue – Gayan Pathirage Apr 11 '17 at 02:49
  • 3
    @Luke, Because I arrived here looking for a way to unset it in All sessions - so this answer provided exactly what I wasn't looking for. – Pacerier Jul 29 '17 at 07:58
43

From PowerShell you can use the .NET [System.Environment]::SetEnvironmentVariable() method:

  • To remove a user environment variable named FOO:

    [Environment]::SetEnvironmentVariable('FOO', $null, 'User')
    

Note that $null is used to better signal the intent to remove the variable, though technically it is effectively the same as passing '' in this case.

  • To remove a system (machine-level) environment variable named FOO - requires elevation (must be run as administrator):

    [Environment]::SetEnvironmentVariable('FOO', $null, 'Machine')
    

Aside from faster execution, the advantage over the reg.exe-based method is that other applications are notified of the change, via a WM_SETTINGCHANGE message - while few applications actually listen to that message and update their environment in response, the Windows (GUI) shell does, so that applications subsequently launched via File Explorer / from the desktop / the taskbar / the Start Menu do see the updated environment.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 4
    This is the best answer here. – James Nov 05 '18 at 17:13
  • 2
    This method avoids the need of rebooting. What an elegant solution ! – jyao Feb 02 '19 at 06:36
  • Like the solution however I cannot include that in a batch file; when executed says 'The filename, directory name, or volume label syntax is incorrect' – Alejandro González Mar 17 '22 at 14:48
  • 1
    @AlejandroGonzález, you can certainly make it work from a batch file. it sounds like you have an unrelated escaping/quoting problem in connection with the PowerShell [CLI](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe). I encourage you to ask a new question focused just on that. – mklement0 Mar 17 '22 at 14:57
41

This has been covered quite a bit, but there's a crucial piece of information that's missing. Hopefully, I can help to clear up how this works and give some relief to weary travellers. :-)

Delete From Current Process

Obviously, everyone knows that you just do this to delete an environment variable from your current process:

set FOO=

Persistent Delete

There are two sets of environment variables, system-wide and user.

Delete User Environment Variable:

reg delete "HKCU\Environment" /v FOO /f

Delete System-Wide Environment Variable:

REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOO

Apply Value Without Rebooting

Here's the magic information that's missing! You're wondering why after you do this, when you launch a new command window, the environment variable is still there. The reason is because explorer.exe has not updated its environment. When one process launches another, the new process inherits the environment from the process that launched it.

There are two ways to fix this without rebooting. The most brute-force way is to kill your explorer.exe process and start it again. You can do that from Task Manager. I don't recommend this method, however.

The other way is by telling explorer.exe that the environment has changed and that it should reread it. This is done by broadcasting a Windows message (WM_SETTINGCHANGE). This can be accomplished with a simple PowerShell script. You could easily write one to do this, but I found one in Update Window Settings After Scripted Changes:

if (-not ("win32.nativemethods" -as [type])) {
    add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessageTimeout(
            IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
            uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
        "@
}

$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero

[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE,[uintptr]::Zero, "Environment", 2, 5000, [ref]$result);

Summary

So to delete a user environment variable named "FOO" and have the change reflected in processes you launch afterwards, do the following.

  1. Save the PowerShell script to a file (we'll call it updateenv.ps1).
  2. Do this from the command line: reg delete "HKCU\Environment" /v FOO /f
  3. Run updateenv.ps1.
  4. Close and reopen your command prompt, and you'll see that the environment variable is no longer defined.

Note, you'll probably have to update your PowerShell settings to allow you to run this script, but I'll leave that as a Google-fu exercise for you.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jamie
  • 1,754
  • 16
  • 34
  • Is there any particular reason you don't recommend killing and restarting explorer? I do it all the time. – Hashim Aziz Sep 03 '18 at 03:52
  • Well, there are two that first come to mind. The first is that force-killing processes can cause memory leaks. Yes, processes are supposed to be sand-boxes, but even the Windows Task Manager warns you not to do this lightly. The other more personal reason is my OCD. When you kill and restart Explorer, all of your icons down in the task bar, including the duplicates when you click on one, are rearranged. I like for my icons to stay in the order that I opened things in. – Jamie Sep 21 '18 at 03:01
  • 1
    Wow. The magic command I've been looking for that acts like `source .bashrc` (or its cousins) in Windows. This goes to the top of the "refer-to-this" line for me. – bballdave025 Nov 26 '19 at 22:57
17

Delete Without Rebooting

The OP's question indeed has been answered extensively, including how to avoid rebooting through powershell, vbscript, or you name it.

However, if you need to stick to cmd commands only and don't have the luxury of being able to call powershell or vbscript, you could use the following approach:

rem remove from current cmd instance
  SET FOOBAR=
rem remove from the registry if it's a user variable
  REG delete HKCU\Environment /F /V FOOBAR
rem remove from the registry if it's a system variable
  REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR
rem tell Explorer.exe to reload the environment from the registry
  SETX DUMMY ""
rem remove the dummy
  REG delete HKCU\Environment /F /V DUMMY

So the magic here is that by using "setx" to assign something to a variable you don't need (in my example DUMMY), you force Explorer.exe to reread the variables from the registry, without needing powershell. You then clean up that dummy, and even though that one will stay in Explorer's environment for a little while longer, it will probably not harm anyone.

Or if after deleting variables you need to set new ones, then you don't even need any dummy. Just using SETX to set the new variables will automatically clear the ones you just removed from any new cmd tasks that might get started.

Background information: I just used this approach successfully to replace a set of user variables by system variables of the same name on all of the computers at my job, by modifying an existing cmd script. There are too many computers to do it manually, nor was it practical to copy extra powershell or vbscripts to all of them. The reason I urgently needed to replace user with system variables was that user variables get synchronized in roaming profiles (didn't think about that), so multiple machines using the same windows login but needing different values, got mixed up.

Ronny D'Hoore
  • 752
  • 7
  • 9
15

I agree with CupawnTae.

SET is not useful for changes to the master environment.

FYI: System variables are in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment (a good deal longer than user vars).

The full command for a system var named FOOBAR therefore is:

REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V FOOBAR

(Note the quotes required to handle the space.)

It is too bad the setx command doesn't support a delete syntax. :(

PS: Use responsibly - If you kill your path variable, don't blame me!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
DougWare
  • 151
  • 1
  • 2
11

The command in DougWare's answer did not work, but this did:

reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v FOOBAR /f

The shortcut HKLM can be used for HKEY_LOCAL_MACHINE.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user4297498
  • 111
  • 1
  • 2
  • 1
    Also, the user environment variables are under "HKCU\Environment" – tzrlk May 22 '17 at 21:50
  • 1
    @Tzrlk, What's the reason for the mismatch? Why is it not in HKLM\Environment there? – Pacerier Jul 29 '17 at 08:03
  • @Pacerier: I have no idea why they put them in such completely separate locations, but if you want to make sure that you've removed either/both system or/and user variables, it helps to know that they're in _completely_ different places. – tzrlk Jul 30 '17 at 22:35
  • 2
    @Tzrlk, Must be some screwed design on Windows side again. – Pacerier Aug 06 '17 at 22:08
3
setx FOOBAR ""

just causes the value of FOOBAR to be a null string. (Although, it shows with the set command with the "" so maybe double-quotes is the string.)

I used:

set FOOBAR=

and then FOOBAR was no longer listed in the set command. (Log-off was not required.)

Windows 7 32 bit, using the command prompt, non-administrator is what I used. (Not cmd or Windows + R, which might be different.)

BTW, I did not see the variable I created anywhere in the registry after I created it. I'm using RegEdit not as administrator.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PReinie
  • 57
  • 1
  • 4
2

You can also create a small VBScript script:

Set env = CreateObject("WScript.Shell").Environment("System")
If env(WScript.Arguments(0)) <> vbNullString Then env.Remove WScript.Arguments(0)

Then call it like %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.

The disadvantage is you need an extra script, but it does not require a reboot.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wernfried Domscheit
  • 54,457
  • 9
  • 76
  • 110
-1

By the way I just figured out how to unset a permanent variable that you've set using setx.

Simply write quotation marks, like:

setx myvar ""

And on next cmd window restart, if you search for the variable

set myvar

There won't be anything set for it.

Alex Mm
  • 65
  • 1
  • 1
  • 7
-1

In PowerShell, the way to delete an Registry value is with the Remove-ItemProperty cmdlet. In this case, the persistent value (for future processes) is removed with:

Remove-ItemProperty HKCU:\Environment FOOBAR

And if you wish to remove it from the current environment, you can just remove it from the Env: "drive" like so:

rm env:\FOOBAR

SETX.exe cannot be used to do this.

Michael Erickson
  • 3,881
  • 2
  • 20
  • 16