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.
- Save the PowerShell script to a file (we'll call it updateenv.ps1).
- Do this from the command line: reg delete "HKCU\Environment" /v FOO /f
- Run updateenv.ps1.
- 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.