命令行从操作系统级配置中删除环境变量

Windows有setx命令:

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

所以你可以这样设置一个变量:

setx FOOBAR 1

你可以像这样清除这个值:

setx FOOBAR ""

但是,该变量不会被删除。它保留在注册表中:

foobar

那么如何移除变量呢?

406681 次浏览

从当前环境(永久删除)中删除变量:

set FOOBAR=

永久性地从用户环境中删除变量(这是setx将其放置的默认位置):

REG delete HKCU\Environment /F /V FOOBAR

如果变量是在系统环境中设置的(例如,如果你最初使用setx /M设置它),作为管理员运行:

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

注意:上面的REG命令不会影响任何现有进程(以及一些从现有进程中分叉出来的新进程),所以如果对立即生效的更改很重要,最简单和最可靠的方法是注销并重新登录或重新启动。如果这不是一个选择,或者您想深入挖掘,这里的一些其他答案有一些很好的建议,可能适合您的用例。

要从当前命令会话中删除变量而不永久删除它,使用常规内置的set命令-只要在等号后面不放任何东西:

set FOOBAR=

要确认,运行不带参数的set并检查当前环境。该变量应该从列表中完全消失。

请注意:这只会从当前环境中删除变量——它不会将更改保存到注册表中。当启动一个新的命令进程时,该变量将返回。

我同意与CupawnTae

SET对于改变主环境是没有用的。

供参考:系统变量在HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment中(比用户变量长得多)。

因此,一个名为FOOBAR的系统变量的完整命令是:

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

(请注意处理空格所需的引号。)

setx命令不支持删除语法真是太糟糕了。:(

PS:负责任地使用-如果你杀死了你的路径变量,不要怪我!

DougWare的回答中的命令不起作用,但是下面的命令起作用了:

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

快捷方式HKLM可用于HKEY_LOCAL_MACHINE

setx FOOBAR ""

只是导致FOOBAR的值为空字符串。(虽然,它显示与set命令与""所以双引号可能是字符串。)

我使用:

set FOOBAR=

然后FOOBAR就不再列在set命令中了。(不需要注销。)

7 32位,使用命令提示符,非管理员是我使用的。(不是cmd或窗户 + R,这可能是不同的。)

顺便说一句,我没有看到我在注册表的任何地方创建的变量,我创建了它。我使用注册表编辑器而不是作为管理员。

这一点已经被讨论了很多,但是有一个关键的信息被遗漏了。希望我能帮你弄清楚这是如何运作的,并给疲惫的旅行者一些安慰。:-)

从当前进程删除

显然,每个人都知道这样做只是为了从当前进程中删除一个环境变量:

set FOO=

永久删除

有两组环境变量,系统范围变量和用户变量。

删除用户环境变量: .使用实例

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

Delete System-Wide Environment Variable: .输出说明

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

在不重启的情况下应用值

这里是被遗漏的神奇信息!您可能想知道,为什么在执行此操作之后,当启动一个新的命令窗口时,环境变量仍然存在。原因是explorer.exe没有更新它的环境。当一个进程启动另一个进程时,新进程从启动它的进程继承环境。

有两种方法可以在不重启的情况下修复这个问题。最残酷的方法是杀死你的explorer.exe进程并重新启动它。你可以从任务管理器开始。但是,我不推荐这种方法。

另一种方法是告诉explorer.exe环境已经改变,它应该重新读取它。这是通过广播一个Windows消息(WM_SETTINGCHANGE)来完成的。这可以用一个简单的PowerShell脚本来完成。你可以很容易地写一个这样做,但我在更新脚本更改后的窗口设置 .中找到了一个:

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);

总结

因此,要删除名为“FOO”的用户环境变量,并将更改反映在随后启动的进程中,请执行以下操作。

  1. 将PowerShell脚本保存到一个文件(我们将其称为updateenv.ps1)。
  2. reg delete "HKCU\Environment" /v FOO /f
  3. updateenv.ps1运行。
  4. 关闭并重新打开命令提示符,您将看到不再定义环境变量。

注意,您可能需要更新PowerShell设置以允许您运行此脚本,但我将把它作为Google-fu练习留给您

你也可以创建一个小的VBScript脚本:

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

然后像%windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR那样调用它。

缺点是需要额外的脚本,但不需要重新启动。

PowerShell中,你可以使用。net [System.Environment]::SetEnvironmentVariable()方法:

  • 删除用户环境变量命名为FOO:

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

注意,$null用于更好地表示remove变量的意图,尽管在这种情况下,从技术上讲,它实际上与传递''相同。

  • 删除系统(机器级)环境变量命名为FOO - 需要高度(必须以管理员身份运行):

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

除了更快的执行速度外,相对于reg.exe-based方法的优势是其他应用程序将收到更改通知,通过WM_SETTINGCHANGE消息-而很少有应用程序实际上侦听该消息并更新其环境作为响应,Windows (GUI) shell ,因此随后通过文件资源管理器/从桌面/任务栏/开始菜单启动的应用程序会看到更新的环境。

不重启删除

OP的问题确实已经得到了广泛的回答,包括如何避免通过powershell、vbscript或任何你能想到的重新启动。

然而,如果你需要坚持只使用cmd命令,并且没有能够调用powershell或vbscript的奢侈,你可以使用以下方法:

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

所以这里的神奇之处在于,通过使用“setx”将一些东西分配给一个你不需要的变量(在我的例子中是DUMMY),你可以强制Explorer.exe从注册表中重新读取变量,而不需要powershell。然后你清理这个假人,尽管它会在“探索者”的环境中停留一段时间,但它可能不会伤害任何人。

或者如果在删除变量后你需要设置新的变量,那么你甚至不需要任何dummy。只要使用SETX来设置新变量,就会自动清除你刚刚从任何可能启动的新cmd任务中删除的那些变量。

背景信息:我刚刚使用这种方法,通过修改现有的cmd脚本,在我工作的所有计算机上成功地将一组用户变量替换为同名的系统变量。有太多的计算机无法手动完成,而且将额外的powershell或vbscript复制到所有计算机上也不现实。我迫切需要用系统变量替换user的原因是用户变量在漫游配置文件中同步(没有想到这一点),所以多台机器使用相同的windows登录,但需要不同的值,弄混了。

顺便说一下,我刚刚弄清楚如何取消使用对于setx设置的永久变量。

简单地写引号,比如:

setx myvar ""

并在下一个cmd窗口重新启动,如果你搜索变量

set myvar

不会有任何安排。

在PowerShell中,删除注册表值的方法是使用Remove-ItemProperty cmdlet。在这种情况下,持久化值(用于将来的进程)被删除:

Remove-ItemProperty HKCU:\Environment FOOBAR

如果您希望将其从当前环境中移除,您可以将其从Env: "drive"像这样:

rm env:\FOOBAR

不能使用SETX.exe来执行此操作。