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


182

Windows具有以下setx命令:

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

因此,您可以像这样设置变量:

setx FOOBAR 1

您可以像这样清除值:

setx FOOBAR ""

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

foob​​ar

那么,您实际上将如何删除该变量?


3
setx只是设置变量。您只是用该行将其空白。
Fox Wilson


由于花了我很多时间进行挖掘,因此有关非命令行选项,另请参见superuser.com/q/297947/46834
加里

Answers:


211

要从当前环境中删除变量(不是永久性地):

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上面的命令不会影响任何现有流程(以及从现有流程派生的一些新流程),因此,如果使更改立即生效很重要,那么最简单,最确定的操作是注销并重新登录或重新启动。如果这不是一个选择,或者您想更深入地进行研究,则此处的其他一些答案将提供一些适合您的用例的好建议。


1
该解决方案似乎不起作用-或我误解了一些基本知识。我做的setx JUNK Hello。打开新的cmd。输入echo %JUNK%并获取Hello。然后,执行操作REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNK,并确认该值已从注册表中消失。我打开新的cmd并输入echo %JUNK%,仍然得到Hello。搜索注册表显示“ JUNK”不存在。请不要告诉我您需要重启!
caasjj

谢谢回复。我正在从“开始”菜单中打开一个新的命令窗口。我已经尝试过两个版本的命令。实际上,当我第一次键入user环境命令时,它会成功。然后,当我重新输入命令时,我得到了The system was unable to find the specified registry or key value。另外,JUNK在注册表中进行全局搜索regedit不会显示任何内容。不过,当我打开一个新的Command窗口(通过Start / accessories或Run中的cmd.exe)并键入时echo %JUNK%,该值仍然存在!
caasjj '16

1
啊! 您认为这样做的合理性是什么?我总是尽可能避免使用admin-UNIX / BSD / Linux的培养。感谢密尔的辛勤工作。+1
caasjj '16

4
也许仅仅是语义,但是(从注册表中)删除立即生效。在再次登录之前,不会从注册表中重新初始化环境。您可以结合使用这2条命令将其从当前环境中删除(它将从SET下一个cmd shell 的列表中删除),然后将其从注册表中删除,例如:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Luke

1
不重新启动就无法更新环境的原因是因为explorer.exe不知道它已被更新。完整说明和解决方案请参见我的回答。
杰米

71

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

set FOOBAR=

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

注意:这只会从当前环境中删除变量-不会将更改持久保存到注册表中。当开始新的命令过程时,变量将返回。


76
这绝对不是答案,我感到不安的是,有这么多赞成票。这仅对当前命令会话有效。启动一个新的命令窗口,然后var返回。
joescii 2014年

6
@joescii您觉得这令人惊讶吗?这回答了问题标题中的问题。所以很明显,问题标题需要更具体。
2014年

10
@oberlies我不同意它回答标题中的问题,因为这在OS级别上无效,而仅在当前命令窗口中有效。其次,您的观点表明问题的详细信息部分无关紧要。
joescii 2014年

3
不幸的是,@ oberlies编辑似乎并没有解决问题-它仍在投票。我想人们会发现它即使没有回答实际的问题也很有用,在这种情况下,它应该受到赞誉(是吗?)。至少它没有被标记为已接受,这会产生误导。
CupawnTae 2015年

3
我应该评论为什么我投票不足。显然是因为这仅在当前会话中有效。
伊恩·格兰杰

22

内容已经涵盖了很多,但是其中缺少一些关键信息。希望我能帮忙弄清它的工作原理,并为疲倦的旅行者提供一些帮助。:-)

从当前进程中删除

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

set FOO=

永久删除

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

删除用户环境变量:

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

删除系统范围的环境变量:

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删除“ HKCU \ Environment” / v FOO / f
  3. 运行updateenv.ps1。
  4. 关闭并重新打开命令提示符,您将看到不再定义环境变量。

请注意,您可能必须更新PowerShell设置才能运行此脚本,但我将其留给您进行Google-fu练习。


您是否有任何不建议您停止并重新启动资源管理器的特定原因?我一直都这样做。
Prometheus

好吧,首先想到两个。首先是强制终止过程可能导致内存泄漏。是的,进程应该是沙盒,但是即使Windows Task Manager也会警告您不要轻易这样做。另一个个人原因是我的强迫症。当您杀死并重新启动资源管理器时,将重新排列任务栏中所有的图标,包括单击时的重复图标。我希望我的图标保持打开状态的顺序
Jamie

1
哇。我一直在寻找的魔术命令source .bashrc在Windows 中的作用类似于(或其表亲)。对于我来说,这是“引用此”行的顶部。
bballdave025

18

PowerShell中,您可以使用.NET [System.Environment]::SetEnvironmentVariable()方法:

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

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

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

  • 删除名为FOO- 系统(计算机级)环境变量需要海拔(必须以管理员身份运行):

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

除了执行速度更快之外,reg.exe基于-方法的优点还在于,其他应用程序会通过一条WM_SETTINGCHANGE消息通知该更改(尽管并非所有应用程序都在监听该消息)。


2
这是最好的答案。
詹姆斯

1
此方法避免了重新启动的需要。多么优雅的解决方案!
jyao

13

我同意CupawnTae

SET 对更改主环境没有用。

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

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

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

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

太可惜了 setx命令不支持删除语法。:(

PS:负责任地使用-如果您杀死了path变量,请不要怪我!


在原始问题中明确提到的@CMCDragonkai-它不会删除注册表项,只是将其空白。实际的问题是如何从注册表中删除它
CupawnTae 2015年

1
我只是添加您,可能需要重新启动/刷新cmd才能生效。
jiggunjer

@jiggunjer,如何刷新?
佩里耶

@Pacerier只是打开一个新终端。
jiggunjer

11

DougWare的答案中的命令不起作用,但是这样做:

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

该快捷方式HKLM可用于HKEY_LOCAL_MACHINE


1
此外,用户环境变量位于“ HKCU \ Environment”下
tzrlk

1
@Tzrlk,不匹配的原因是什么?为什么不在HKLM \环境中?
Pacerier '17

@Pacerier:我不知道为什么将它们放置在如此完全分开的位置,但是如果您要确保已删除系统变量和/或用户变量,则有助于了解它们是否完全不同的地方。
tzrlk

2
@Tzrlk,必须再次在Windows端进行一些拧紧设计。
佩里耶

4

删除而不重新启动

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。然后,您清理该虚拟对象,即使该虚拟对象将在Explorer的环境中停留一会儿,也可能不会伤害任何人。

或者,如果在删除变量后需要设置新变量,那么您甚至不需要任何虚拟变量。仅使用SETX设置新变量将自动清除您刚刚从可能开始的任何新cmd任务中删除的变量。

背景信息:我刚刚通过修改现有的cmd脚本成功地使用了这种方法,用我所有工作的所有计算机上的同名系统变量替换了一组用户变量。太多的计算机无法手动执行此操作,将多余的powershell或vbscript复制到所有这些计算机上也不可行。我迫切需要用系统变量替换用户的原因是,用户变量在漫游配置文件中得到了同步(没有考虑这一点),因此使用同一Windows登录名但需要不同值的多台计算机混杂在一起。


3
setx FOOBAR ""

只是使FOOBAR的值为空字符串。(尽管它与set带有“”命令一起所以字符串可能双引号。)

我用了:

set FOOBAR=

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

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

顺便说一句,创建变量后,在注册表中的任何地方都看不到变量。我不是以管理员身份使用RegEdit


1

您还可以创建一个小的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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.