Línea de comando para eliminar una variable de entorno de la configuración de nivel del sistema operativo

182

Windows tiene el setxcomando:

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

Entonces puede establecer una variable como esta:

setx FOOBAR 1

Y puede borrar el valor de esta manera:

setx FOOBAR ""

Sin embargo, la variable no se elimina. Se queda en el registro:

foobar

Entonces, ¿cómo eliminarías realmente la variable?

Peter Mortensen
fuente
3
setx solo establece la variable. Solo lo estás dejando en blanco con esa línea.
Fox Wilson el
1
ver también stackoverflow.com/questions/1472722/…
Brian Burns
Como me llevó bastante tiempo excavar, consulte también superuser.com/q/297947/46834 para conocer las opciones de la línea de comandos.
Gary

Respuestas:

217

Para eliminar la variable del entorno actual ( no de forma permanente):

set FOOBAR=

Para eliminar permanentemente la variable del entorno del usuario (que es el lugar predeterminado, la setxcoloca):

REG delete HKCU\Environment /F /V FOOBAR

Si la variable se configura en el entorno del sistema (por ejemplo, si la configuró originalmente setx /M), como administrador ejecute:

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

Nota: Los REGcomandos anteriores no afectarán ningún proceso existente (y algunos procesos nuevos que se bifurcan a partir de procesos existentes), por lo que si es importante que el cambio surta efecto de inmediato, lo más fácil y seguro es cerrar sesión y volver a iniciarla o reiniciar. Si esto no es una opción o si desea profundizar, algunas de las otras respuestas aquí tienen algunas sugerencias excelentes que pueden adaptarse a su caso de uso.

CupawnTae
fuente
1
Esta solución no parece funcionar, o no estoy entendiendo algo básico. Hago setx JUNK Hello. Abrir nuevo cmd. Escribe echo %JUNK%y obtén Hello. Luego lo hago REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNKy confirmo que el valor se ha ido del registro. Abro un nuevo cmd y escribo echo %JUNK%y sigo obteniendo Hello. La búsqueda en el registro no muestra la presencia de 'JUNK'. ¡No me digas que necesitas reiniciar!
caasjj 05 de
Gracias por la respuesta. Estoy abriendo una nueva ventana de comandos desde el menú Inicio. He intentado ambas versiones del comando. De hecho, la primera vez que escribo el usercomando de entorno, tiene éxito. Luego, cuando vuelvo a escribir el comando que recibo The system was unable to find the specified registry or key value. Además, una búsqueda global JUNKen el registro con regeditnada resulta. Aún así, cuando abro una nueva ventana de Comando (a través de Inicio / accesorios, o cmd.exe en Ejecutar) y escribo echo %JUNK%, ¡el valor sigue ahí!
caasjj 05 de
1
Ah! ¿Qué supones que es racional para eso? Siempre evito el administrador tanto como sea posible: educación UNIX / BSD / Linux. Muchas gracias por la increíble diligencia. +1
caasjj
44
tal vez sea solo semántica, pero la eliminación (del registro) surte efecto inmediatamente. El entorno no se reinicia desde el registro hasta que vuelva a iniciar sesión. Puede combinar los 2 comandos para eliminarlo del entorno actual (que lo eliminará de la SETlista para el próximo shell de cmd) y luego eliminarlo del registro, por ejemplo:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Lucas
1
La razón por la que el entorno no parece actualizarse sin reiniciar es porque explorer.exe no sabe que se ha actualizado. Vea mi respuesta para obtener una explicación completa y una solución.
Jamie
72

Para eliminar la variable de la sesión de comando actual sin eliminarla permanentemente, use el setcomando incorporado regular , simplemente no ponga nada después del signo igual:

set FOOBAR=

Para confirmar, ejecute setsin argumentos y verifique el entorno actual. La variable debería faltar por completo de la lista.

Nota : esto solo eliminará la variable del entorno actual ; no persistirá el cambio en el registro. Cuando se inicia un nuevo proceso de comando, la variable volverá.

Brian Kelly
fuente
77
Esta definitivamente NO es la respuesta, y me parece inquietante que haya tantos votos positivos. Esto solo es efectivo para la sesión de comando actual. Poner en marcha una nueva ventana de comandos, y la var está de vuelta.
joescii
66
@joescii ¿Te parece sorprendente? Esto respondió la pregunta en el título de la pregunta. Entonces, obviamente, el título de la pregunta tenía que ser más específico.
Oberlies
10
@oberlies No estoy de acuerdo con que responda la pregunta en el título, porque esto NO funciona a nivel del sistema operativo, sino solo en la ventana de comandos actual. En segundo lugar, su punto sugiere que la parte de detalles de la pregunta es irrelevante.
joescii
3
@oberlies desafortunadamente, la edición no parece haber funcionado, todavía está recibiendo votos a favor. Supongo que la gente lo encuentra útil incluso si no responde la pregunta real, en cuyo caso tal vez merezca los votos positivos (¿verdad?). Al menos no está marcado como aceptado, lo que sería engañoso.
CupawnTae
3
Se supone que debo comentar por qué voté en contra. Obviamente porque esto solo funciona en la sesión actual.
Ian Grainger
22

Esto se ha cubierto bastante, pero falta información crucial. Con suerte, puedo ayudar a aclarar cómo funciona esto y dar un poco de alivio a los viajeros cansados. :-)

Eliminar del proceso actual

Obviamente, todos saben que usted hace esto para eliminar una variable de entorno de su proceso actual:

set FOO=

Eliminar persistente

Hay dos conjuntos de variables de entorno, todo el sistema y usuario.

Eliminar la variable de entorno del usuario:

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

Eliminar la variable de entorno de todo el sistema:

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

Aplicar valor sin reiniciar

¡Aquí está la información mágica que falta! Se pregunta por qué después de hacer esto, cuando inicia una nueva ventana de comandos, la variable de entorno sigue ahí. La razón es porque explorer.exe no ha actualizado su entorno. Cuando un proceso inicia otro, el nuevo proceso hereda el entorno del proceso que lo lanzó.

Hay dos formas de solucionar esto sin reiniciar. La forma más brutal es matar el proceso de explorer.exe y comenzarlo de nuevo. Puede hacerlo desde el Administrador de tareas . Sin embargo, no recomiendo este método.

La otra forma es decirle a explorer.exe que el entorno ha cambiado y que debería releerlo. Esto se hace transmitiendo un mensaje de Windows (WM_SETTINGCHANGE). Esto se puede lograr con un simple script de PowerShell. Podrías escribir fácilmente uno para hacer esto, pero encontré uno en la Configuración de la ventana de actualización después de los cambios en el script :

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

Resumen

Por lo tanto, para eliminar una variable de entorno de usuario llamada "FOO" y hacer que el cambio se refleje en los procesos que inicie después, haga lo siguiente.

  1. Guarde el script de PowerShell en un archivo (lo llamaremos updateenv.ps1).
  2. Haga esto desde la línea de comando: reg delete "HKCU \ Environment" / v FOO / f
  3. Ejecute updateenv.ps1.
  4. Cierre y vuelva a abrir su símbolo del sistema, y ​​verá que la variable de entorno ya no está definida.

Tenga en cuenta que probablemente tendrá que actualizar su configuración de PowerShell para permitirle ejecutar este script, pero lo dejaré como un ejercicio de Google-fu para usted.

Jamie
fuente
¿Hay alguna razón en particular por la que no recomiende matar y reiniciar el explorador? Lo hago todo el tiempo.
Prometheus
Bueno, hay dos que primero vienen a la mente. El primero es que los procesos de destrucción forzada pueden causar pérdidas de memoria. Sí, se supone que los procesos son cajas de arena, pero incluso el Administrador de tareas de Windows le advierte que no lo haga a la ligera. La otra razón más personal es mi TOC. Cuando matas y reinicias el Explorador, todos tus íconos en la barra de tareas, incluidos los duplicados cuando haces clic en uno, se reorganizan. Me gusta que mis íconos se mantengan en el orden en que abrí las cosas.
Jamie
1
Guau. El comando mágico que he estado buscando actúa como source .bashrc(o sus primos) en Windows. Esto va a la parte superior de la línea "referir a esto" para mí.
bballdave025
19

Desde PowerShell puede usar el [System.Environment]::SetEnvironmentVariable()método .NET :

  • Para eliminar una variable de entorno de usuario llamada FOO:

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

Tenga en cuenta que $nullse utiliza para indicar mejor la intención de eliminar la variable, aunque técnicamente es efectivamente lo mismo que pasar ''en este caso.

  • Para eliminar una variable de entorno del sistema (nivel de máquina) denominada FOO: requiere elevación (debe ejecutarse como administrador):

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

Además de una ejecución más rápida, la ventaja sobre el reg.exemétodo basado es que otras aplicaciones son notificadas del cambio , a través de un WM_SETTINGCHANGEmensaje (aunque no todas las aplicaciones escuchan ese mensaje).

mklement0
fuente
2
Esta es la mejor respuesta aquí.
James
1
Este método evita la necesidad de reiniciar. ¡Qué solución tan elegante!
jyao
13

Estoy de acuerdo con CupawnTae .

SET no es útil para cambios en el entorno maestro.

FYI: las variables del sistema están en HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment(mucho más tiempo que los usuarios var)

El comando completo para un sistema var llamado FOOBAR es:

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

(Tenga en cuenta las citas necesarias para manejar el espacio).

Es una lástima que el setxcomando no sea compatible con una sintaxis de eliminación. :(

PD: Úselo responsablemente: si mata su variable de ruta, ¡no me culpe!

DougWare
fuente
@CMCDragonkai que se menciona explícitamente en la pregunta original: no elimina la entrada del registro, solo la deja en blanco. La pregunta real es cómo eliminarlo del registro
CupawnTae
1
Solo agregaría que es posible que deba reiniciar / actualizar cmd antes de que esto surta efecto.
jiggunjer
@jiggunjer, ¿Cómo actualizar?
Pacerier
@Pacerier acaba de abrir una nueva terminal.
jiggunjer
11

El comando en la respuesta de DougWare no funcionó, pero sí:

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

El atajo HKLMse puede usar para HKEY_LOCAL_MACHINE.

usuario4297498
fuente
1
Además, las variables de entorno del usuario están en "HKCU \ Environment"
tzrlk
1
@Tzrlk, ¿Cuál es la razón de la falta de coincidencia? ¿Por qué no está en HKLM \ Environment allí?
Pacerier
@Pacerier: No tengo ni idea de por qué los pusieron en esos lugares completamente separados, pero si usted quiere asegurarse de que usted ha quitado ya sea / tanto el sistema y / o variables de usuario, es muy útil saber que están en completo diferente lugares.
tzrlk
2
@Tzrlk, debe haber algún diseño atornillado en el lado de Windows nuevamente.
Pacerier
4

Eliminar sin reiniciar

De hecho, la pregunta del OP se ha respondido ampliamente, incluido cómo evitar reiniciar a través de powershell, vbscript o lo que sea.

Sin embargo, si necesita apegarse solo a los comandos cmd y no puede darse el lujo de poder llamar a powershell o vbscript, puede usar el siguiente enfoque:

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

Entonces, la magia aquí es que al usar "setx" para asignar algo a una variable que no necesita (en mi ejemplo DUMMY), obliga a Explorer.exe a releer las variables del registro, sin necesidad de PowerShell. Luego limpia ese maniquí, y aunque ese permanecerá en el entorno de Explorer por un tiempo más, probablemente no dañará a nadie.

O si después de eliminar variables necesita establecer otras nuevas, entonces ni siquiera necesita ningún ficticio. Simplemente usando SETX para establecer las nuevas variables borrará automáticamente las que acaba de eliminar de cualquier nueva tarea de cmd que pueda comenzar.

Información general: acabo de utilizar este enfoque con éxito para reemplazar un conjunto de variables de usuario por variables del sistema con el mismo nombre en todas las computadoras en mi trabajo, modificando un script de cmd existente. Hay demasiadas computadoras para hacerlo manualmente, y tampoco era práctico copiar powershell o vbscripts adicionales en todas ellas. La razón por la que necesitaba reemplazar urgentemente al usuario con variables del sistema era que las variables del usuario se sincronizaban en los perfiles móviles (no pensé en eso), por lo que varias máquinas que usaban el mismo inicio de sesión de Windows pero necesitaban valores diferentes, se confundieron.

Ronny D'Hoore
fuente
3
setx FOOBAR ""

solo hace que el valor de FOOBAR sea una cadena nula. (Aunque, se muestra con el setcomando con el "", entonces quizás las comillas dobles son la cadena).

Solía:

set FOOBAR=

y luego FOOBAR ya no figuraba en el comando set. (No fue necesario cerrar sesión).

Windows 7 de 32 bits, utilizando el símbolo del sistema, no administrador es lo que utilicé. (No cmd o Windows+ R, que podría ser diferente).

Por cierto, no vi la variable que creé en ninguna parte del registro después de haberla creado. Estoy usando RegEdit no como administrador.

PReinie
fuente
1

También puede crear un pequeño script VBScript :

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

Entonces llámalo como %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.

La desventaja es que necesita un script adicional, pero no requiere un reinicio.

Wernfried Domscheit
fuente