Ligne de commande pour supprimer une variable d'environnement de la configuration au niveau du système d'exploitation

182

Windows a la setxcommande:

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

Vous pouvez donc définir une variable comme celle-ci:

setx FOOBAR 1

Et vous pouvez effacer la valeur comme ceci:

setx FOOBAR ""

Cependant, la variable n'est pas supprimée. Il reste dans le registre:

foobar

Alors, comment supprimeriez-vous réellement la variable?

Peter Mortensen
la source
3
setx définit simplement la variable. Vous le supprimez simplement avec cette ligne.
Fox Wilson
1
voir aussi stackoverflow.com/questions/1472722/…
Brian Burns
Puisqu'il m'a fallu beaucoup de fouilles, consultez également superuser.com/q/297947/46834 pour les options hors ligne de commande.
gary

Réponses:

217

Pour supprimer la variable de l'environnement actuel ( pas de façon permanente):

set FOOBAR=

Pour supprimer définitivement la variable de l' environnement utilisateur (qui est l'emplacement par défaut setx):

REG delete HKCU\Environment /F /V FOOBAR

Si la variable est définie dans l' environnement système (par exemple, si vous la définissez à l'origine avec setx /M), en tant qu'administrateur, exécutez:

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

Remarque: les REGcommandes ci-dessus n'affecteront aucun processus existant (et certains nouveaux processus issus de processus existants), donc s'il est important que le changement prenne effet immédiatement, la chose la plus simple et la plus sûre à faire est de vous déconnecter et de vous reconnecter ou redémarrer. Si ce n'est pas une option ou si vous souhaitez approfondir, certaines des autres réponses ici contiennent d'excellentes suggestions qui peuvent convenir à votre cas d'utilisation.

CupawnTae
la source
1
Cette solution ne semble pas fonctionner - ou je ne comprends pas quelque chose de basique. Je fais setx JUNK Hello. Ouvrez un nouveau cmd. Tapez echo %JUNK%et obtenez Hello. Ensuite, je le fais REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNKet je confirme que la valeur a disparu du registre. J'ouvre un nouveau cmd et tape echo %JUNK%et je reçois toujours Hello. La recherche dans le registre ne montre aucune présence de «JUNK». Ne me dites pas que vous avez besoin d'un redémarrage!
caasjj
Merci pour la réponse. J'ouvre une nouvelle fenêtre de commande à partir du menu Démarrer. J'ai essayé les deux versions de la commande. En fait, la première fois que je tape la usercommande d'environnement, cela réussit. Ensuite, lorsque je retaper la commande, je reçois The system was unable to find the specified registry or key value. De plus, une recherche globale JUNKdans le registre avec regeditne donne rien. Pourtant, lorsque j'ouvre une nouvelle fenêtre de commande (via Démarrer / accessoires ou cmd.exe dans Exécuter) et que je tape echo %JUNK%, la valeur est toujours là!
caasjj
1
Ah! Que pensez-vous du rationnel pour cela? J'évite toujours autant que possible l'administration - l'éducation UNIX / BSD / Linux. Merci mille fois pour la diligence impressionnante. +1
caasjj
4
c'est peut-être juste de la sémantique, mais la suppression (du registre) prend effet immédiatement. L'environnement n'est pas réinitialisé à partir du registre tant que vous ne vous connectez pas à nouveau. Vous pouvez combiner les 2 commandes pour le supprimer de l'environnement actuel (ce qui le supprimera de la SETliste pour le prochain shell cmd), puis le supprimer du registre, par exemple:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Luke
1
La raison pour laquelle l'environnement ne semble pas être mis à jour sans redémarrage est que explorer.exe ne sait pas qu'il a été mis à jour. Voir ma réponse pour une explication complète et une solution.
Jamie
72

Pour supprimer la variable de la session de commande en cours sans la supprimer définitivement, utilisez la setcommande intégrée standard - ne mettez rien après le signe égal:

set FOOBAR=

Pour confirmer, exécutez setsans argument et vérifiez l'environnement actuel. La variable doit être entièrement absente de la liste.

Remarque : cela supprimera uniquement la variable de l' environnement actuel - cela ne conservera pas la modification du registre. Lorsqu'un nouveau processus de commande est démarré, la variable sera de retour.

Brian Kelly
la source
77
Ce n'est certainement PAS la réponse, et je trouve dérangeant qu'il y ait autant de votes positifs. Ceci n'est effectif que pour la session de commande en cours. Ouvrez une nouvelle fenêtre de commande et le var est de retour.
joescii
6
@joescii Vous trouvez cela surprenant? Cela répond à la question du titre de la question. Donc, évidemment, le titre de la question devait être plus précis.
oberlies
10
@oberlies Je ne suis pas d'accord pour dire que cela répond à la question dans le titre, car cela ne fonctionne PAS au niveau du système d'exploitation, mais uniquement dans la fenêtre de commande actuelle. Deuxièmement, votre argument suggère que la partie des détails de la question n'est pas pertinente.
joescii
3
@oberlies, malheureusement, la modification ne semble pas avoir fait l'affaire - elle reçoit toujours des votes positifs. Je suppose que les gens le trouvent utile même si cela ne répond pas à la question réelle, auquel cas il mérite peut-être les votes positifs (n'est-ce pas?). Au moins, ce n'est pas marqué comme accepté, ce qui serait trompeur.
CupawnTae
3
Je suis censé expliquer pourquoi j'ai voté contre. Evidemment parce que cela ne fonctionne que dans la session en cours.
Ian Grainger
22

Cela a été un peu couvert, mais il manque une information cruciale. J'espère que je pourrai vous aider à comprendre comment cela fonctionne et à soulager les voyageurs fatigués. :-)

Supprimer du processus actuel

De toute évidence, tout le monde sait que vous faites cela pour supprimer une variable d'environnement de votre processus actuel:

set FOO=

Suppression persistante

Il existe deux ensembles de variables d'environnement, à l'échelle du système et utilisateur.

Supprimer la variable d'environnement utilisateur:

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

Supprimer la variable d'environnement à l'échelle du système:

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

Appliquer la valeur sans redémarrer

Voici les informations magiques qui manquent! Vous vous demandez pourquoi après avoir fait cela, lorsque vous lancez une nouvelle fenêtre de commande, la variable d'environnement est toujours là. La raison en est que explorer.exe n'a pas mis à jour son environnement. Lorsqu'un processus en lance un autre, le nouveau processus hérite de l'environnement du processus qui l'a lancé.

Il existe deux façons de résoudre ce problème sans redémarrer. Le moyen le plus brutal est de tuer votre processus explorer.exe et de le redémarrer. Vous pouvez le faire à partir du Gestionnaire des tâches . Cependant, je ne recommande pas cette méthode.

L'autre façon est de dire à explorer.exe que l'environnement a changé et qu'il doit le relire. Cela se fait en diffusant un message Windows (WM_SETTINGCHANGE). Cela peut être accompli avec un simple script PowerShell. Vous pouvez facilement en écrire un pour ce faire, mais j'en ai trouvé un dans les paramètres de la fenêtre de mise à jour après les modifications scriptées :

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

Résumé

Donc, pour supprimer une variable d'environnement utilisateur nommée "FOO" et que le changement soit reflété dans les processus que vous lancez par la suite, procédez comme suit.

  1. Enregistrez le script PowerShell dans un fichier (nous l'appellerons updateenv.ps1).
  2. Faites cela à partir de la ligne de commande: reg delete "HKCU \ Environment" / v FOO / f
  3. Exécutez updateenv.ps1.
  4. Fermez et rouvrez votre invite de commande, et vous verrez que la variable d'environnement n'est plus définie.

Notez que vous devrez probablement mettre à jour vos paramètres PowerShell pour vous permettre d'exécuter ce script, mais je laisserai cela comme un exercice Google-fu pour vous.

Jamie
la source
Y a-t-il une raison particulière pour laquelle vous ne recommandez pas de tuer et de redémarrer l'explorateur? Je le fais tout le temps.
Prometheus
Eh bien, il y en a deux qui me viennent à l'esprit. Le premier est que les processus de destruction forcée peuvent provoquer des fuites de mémoire. Oui, les processus sont censés être des bacs à sable, mais même le Gestionnaire des tâches de Windows vous avertit de ne pas le faire à la légère. L'autre raison plus personnelle est mon TOC. Lorsque vous tuez et redémarrez Explorer, toutes vos icônes dans la barre des tâches, y compris les doublons lorsque vous cliquez sur l'une d'entre elles, sont réorganisées. J'aime que mes icônes restent dans l'ordre dans lequel j'ai ouvert les choses.
Jamie
1
Sensationnel. La commande magique que j'ai recherchée qui agit comme source .bashrc(ou ses cousins) dans Windows. Cela va au sommet de la ligne «refer-to-this» pour moi.
bballdave025
19

À partir de PowerShell, vous pouvez utiliser la [System.Environment]::SetEnvironmentVariable()méthode .NET :

  • Pour supprimer une variable d'environnement utilisateur nommée FOO:

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

Notez que cela $nullest utilisé pour mieux signaler l'intention de supprimer la variable, bien que techniquement, ce soit effectivement la même chose que la transmission ''dans ce cas.

  • Pour supprimer une variable d'environnement système (au niveau de la machine) nommée FOO- nécessite une élévation (doit être exécutée en tant qu'administrateur):

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

Outre une exécution plus rapide, l'avantage par rapport à la reg.exeméthode basée sur la base de données est que les autres applications sont notifiées du changement , via un WM_SETTINGCHANGEmessage (bien que toutes les applications n'écoutent pas ce message).

mklement0
la source
2
C'est la meilleure réponse ici.
James
1
Cette méthode évite d'avoir à redémarrer. Quelle solution élégante!
jyao
13

Je suis d' accord avec CupawnTae .

SET n'est pas utile pour les modifications apportées à l'environnement maître.

FYI: les variables système sont en HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment(beaucoup plus longues que les variables utilisateur).

La commande complète pour une variable système nommée FOOBAR est donc:

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

(Notez les guillemets nécessaires pour gérer l'espace.)

Il est dommage que la setxcommande ne prenne pas en charge une syntaxe de suppression. :(

PS: Utilisez de manière responsable - Si vous tuez votre variable de chemin, ne me blâmez pas!

DougWare
la source
@CMCDragonkai qui est explicitement mentionné dans la question d'origine - il ne supprime pas l'entrée de registre, il la vide simplement. La question réelle est de savoir comment le supprimer du registre
CupawnTae
1
J'ajouterais simplement que vous devrez peut-être redémarrer / actualiser cmd avant que cela ne prenne effet.
jiggunjer
@jiggunjer, comment rafraîchir?
Pacerier
@Pacerier vient d'ouvrir un nouveau terminal.
jiggunjer
11

La commande dans la réponse de DougWare n'a pas fonctionné, mais ceci a fonctionné:

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

Le raccourci HKLMpeut être utilisé pour HKEY_LOCAL_MACHINE.

user4297498
la source
1
De plus, les variables d'environnement utilisateur sont sous "HKCU \ Environment"
tzrlk
1
@Tzrlk, Quelle est la raison de l'inadéquation? Pourquoi n'est-il pas présent dans HKLM \ Environment?
Pacerier
@Pacerier: Je ne sais pas pourquoi ils les placent dans des emplacements aussi complètement séparés, mais si vous voulez vous assurer que vous avez supprimé / les deux variables système ou / et utilisateur, il est utile de savoir qu'elles sont complètement différentes des endroits.
tzrlk
2
@Tzrlk, il doit y avoir à nouveau un design vissé du côté Windows.
Pacerier
4

Supprimer sans redémarrer

La question de l'OP a en effet reçu une réponse approfondie, y compris comment éviter le redémarrage via PowerShell, vbscript ou vous le nommez.

Cependant, si vous devez vous en tenir uniquement aux commandes cmd et que vous n'avez pas le luxe de pouvoir appeler PowerShell ou vbscript, vous pouvez utiliser l'approche suivante:

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

Donc, la magie ici est qu'en utilisant "setx" pour assigner quelque chose à une variable dont vous n'avez pas besoin (dans mon exemple DUMMY), vous forcez Explorer.exe à relire les variables du registre, sans avoir besoin de PowerShell. Vous nettoyez ensuite ce mannequin, et même si celui-ci restera un peu plus longtemps dans l'environnement d'Explorateur, il ne fera probablement de mal à personne.

Ou si, après avoir supprimé des variables, vous devez en définir de nouvelles, vous n'avez même pas besoin de mannequin. Le simple fait d'utiliser SETX pour définir les nouvelles variables effacera automatiquement celles que vous venez de supprimer de toute nouvelle tâche cmd qui pourrait commencer.

Informations générales: Je viens d'utiliser cette approche avec succès pour remplacer un ensemble de variables utilisateur par des variables système du même nom sur tous les ordinateurs de mon travail, en modifiant un script cmd existant. Il y a trop d'ordinateurs pour le faire manuellement, et il n'était pas non plus pratique de copier des PowerShell ou des vbscripts supplémentaires sur chacun d'eux. La raison pour laquelle j'avais un besoin urgent de remplacer l'utilisateur par des variables système était que les variables utilisateur étaient synchronisées dans des profils itinérants (je n'y pensais pas), donc plusieurs machines utilisant le même identifiant Windows mais nécessitant des valeurs différentes, se sont mélangées.

Ronny D'Hoore
la source
3
setx FOOBAR ""

fait simplement que la valeur de FOOBAR est une chaîne nulle. (Bien que cela s'affiche avec la setcommande avec le "", alors peut-être que des guillemets sont la chaîne.)

J'ai utilisé:

set FOOBAR=

puis FOOBAR n'était plus répertorié dans la commande set. (La déconnexion n'était pas nécessaire.)

Windows 7 32 bits, en utilisant l'invite de commande, non-administrateur est ce que j'ai utilisé. (Pas cmd ou Windows+ R, ce qui peut être différent.)

BTW, je n'ai vu la variable que j'ai créée nulle part dans le registre après l'avoir créée. J'utilise RegEdit pas en tant qu'administrateur.

PReinie
la source
1

Vous pouvez également créer un petit script VBScript :

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

Alors appelez-le comme %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.

L'inconvénient est que vous avez besoin d'un script supplémentaire, mais il ne nécessite pas de redémarrage.

Wernfried Domscheit
la source