Befehlszeile zum Entfernen einer Umgebungsvariablen aus der Konfiguration auf Betriebssystemebene

182

Windows hat den setxBefehl:

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

Sie können also eine Variable wie folgt festlegen:

setx FOOBAR 1

Und Sie können den Wert folgendermaßen löschen:

setx FOOBAR ""

Die Variable wird jedoch nicht entfernt. Es bleibt in der Registrierung:

foobar

Wie würden Sie die Variable tatsächlich entfernen?

Peter Mortensen
quelle
3
setx setzt nur die Variable. Sie löschen es nur mit dieser Zeile.
Fox Wilson
1
Siehe auch stackoverflow.com/questions/1472722/…
Brian Burns
Da ich ziemlich viel gegraben habe, finden Sie auch unter superuser.com/q/297947/46834 Optionen für Nicht-Befehlszeilen.
Gary

Antworten:

214

So entfernen Sie die Variable aus der aktuellen Umgebung ( nicht dauerhaft):

set FOOBAR=

So entfernen Sie die Variable dauerhaft aus der Benutzerumgebung (dies ist der Standardort setx):

REG delete HKCU\Environment /F /V FOOBAR

Wenn die Variable in der Systemumgebung festgelegt ist (z. B. wenn Sie sie ursprünglich festgelegt haben setx /M), führen Sie als Administrator Folgendes aus:

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

Hinweis: Die REGobigen Befehle wirken sich nicht auf vorhandene Prozesse aus (und auf einige neue Prozesse, die aus vorhandenen Prozessen abgeleitet wurden). Wenn es also wichtig ist, dass die Änderung sofort wirksam wird, ist es am einfachsten und sichersten, sich abzumelden und wieder anzumelden oder neu starten. Wenn dies keine Option ist oder Sie tiefer gehen möchten, enthalten einige der anderen Antworten hier einige großartige Vorschläge, die möglicherweise zu Ihrem Anwendungsfall passen.

CupawnTae
quelle
1
Diese Lösung scheint nicht zu funktionieren - oder ich verstehe etwas Grundlegendes falsch. Das tue ich setx JUNK Hello. Neues cmd öffnen. Tippe echo %JUNK%und hole Hello. Dann tue ich das REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNKund bestätige, dass der Wert aus der Registrierung verschwunden ist. Ich öffne neue cmd und tippe und echo %JUNK%bekomme immer noch Hello. Die Suche in der Registrierung zeigt keine Anwesenheit von 'JUNK'. Bitte sag mir nicht, dass du einen Neustart brauchst!
Caasjj
Danke für die Antwort. Ich öffne ein neues Befehlsfenster über das Startmenü. Ich habe beide Versionen des Befehls ausprobiert. Tatsächlich ist es erfolgreich, wenn ich den userUmgebungsbefehl zum ersten Mal eingebe. Wenn ich dann den Befehl erneut eingebe, erhalte ich The system was unable to find the specified registry or key value. Auch eine globale Suche JUNKin der Registrierung mit regeditergibt nichts. Wenn ich dennoch ein neues Befehlsfenster öffne (über Start / Zubehör oder cmd.exe in Run) und tippe echo %JUNK%, ist der Wert immer noch da!
Caasjj
1
Ah! Was glaubst du, ist das Rationale dafür? Ich vermeide Admin immer so weit wie möglich - UNIX / BSD / Linux-Erziehung. Vielen Dank für die tolle Sorgfalt. +1
caasjj
4
Vielleicht ist es nur Semantik, aber das Löschen (aus der Registrierung) wird sofort wirksam. Die Umgebung wird erst aus der Registrierung neu initialisiert, wenn Sie sich erneut anmelden. Sie können die beiden Befehle kombinieren, um es aus der aktuellen Umgebung zu entfernen (wodurch es aus der SETListe für die nächste cmd-Shell entfernt wird) und dann aus der Registrierung entfernen, z. B.:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Luke
1
Der Grund, warum die Umgebung ohne Neustart nicht aktualisiert zu werden scheint, ist, dass explorer.exe nicht weiß, dass sie aktualisiert wurde. Siehe meine Antwort für eine vollständige Erklärung und Lösung.
Jamie
72

Verwenden Sie den regulären integrierten setBefehl, um die Variable aus der aktuellen Befehlssitzung zu entfernen, ohne sie dauerhaft zu entfernen. Setzen Sie einfach nichts nach das Gleichheitszeichen:

set FOOBAR=

Führen Sie zur Bestätigung setkeine Argumente aus und überprüfen Sie die aktuelle Umgebung. Die Variable sollte vollständig in der Liste fehlen.

Hinweis : Dadurch wird nur die Variable aus der aktuellen Umgebung entfernt. Die Änderung an der Registrierung wird nicht beibehalten. Wenn ein neuer Befehlsprozess gestartet wird, ist die Variable zurück.

Brian Kelly
quelle
77
Dies ist definitiv NICHT die Antwort, und ich finde es beunruhigend, dass es so viele Up-Votes gibt. Dies gilt nur für die aktuelle Befehlssitzung. Öffnen Sie ein neues Befehlsfenster, und die Variable ist zurück.
joescii
6
@joescii Findest du das überraschend? Dies beantwortete die Frage im Fragentitel. Offensichtlich musste der Titel der Frage genauer sein.
Oberlies
10
@oberlies Ich bin nicht der Meinung, dass es die Frage im Titel beantwortet, da dies NICHT auf Betriebssystemebene funktioniert, sondern nur im aktuellen Befehlsfenster. Zweitens deutet Ihr Punkt darauf hin, dass der Detailteil der Frage irrelevant ist.
Joecii
3
@oberlies Leider scheint die Bearbeitung nicht den Trick getan zu haben - es werden immer noch positive Stimmen abgegeben. Ich denke, die Leute finden es nützlich, auch wenn es die eigentliche Frage nicht beantwortet. In diesem Fall verdient es vielleicht die positiven Stimmen (oder?). Zumindest wird es nicht als akzeptiert markiert, was irreführend wäre.
CupawnTae
3
Ich soll kommentieren, warum ich abgelehnt habe. Offensichtlich, weil dies nur in der aktuellen Sitzung funktioniert.
Ian Grainger
22

Dies wurde schon viel behandelt, aber es fehlt eine wichtige Information. Hoffentlich kann ich helfen, die Funktionsweise zu klären und müden Reisenden Erleichterung zu verschaffen. :-)

Aus aktuellem Prozess löschen

Offensichtlich weiß jeder, dass Sie dies nur tun, um eine Umgebungsvariable aus Ihrem aktuellen Prozess zu löschen:

set FOO=

Dauerhaftes Löschen

Es gibt zwei Sätze von Umgebungsvariablen, systemweit und Benutzer.

Benutzerumgebungsvariable löschen:

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

Systemweite Umgebungsvariable löschen:

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

Wert ohne Neustart anwenden

Hier sind die magischen Informationen, die fehlen! Sie fragen sich, warum die Umgebungsvariable nach dem Starten eines neuen Befehlsfensters immer noch vorhanden ist. Der Grund dafür ist, dass explorer.exe seine Umgebung nicht aktualisiert hat. Wenn ein Prozess einen anderen startet, erbt der neue Prozess die Umgebung von dem Prozess, der ihn gestartet hat.

Es gibt zwei Möglichkeiten, dies zu beheben, ohne neu zu starten. Am brutalsten ist es, den Prozess explorer.exe zu beenden und erneut zu starten. Sie können dies über den Task-Manager tun . Ich empfehle diese Methode jedoch nicht.

Der andere Weg besteht darin, explorer.exe mitzuteilen, dass sich die Umgebung geändert hat und dass sie erneut gelesen werden sollte. Dies erfolgt durch Senden einer Windows-Nachricht (WM_SETTINGCHANGE). Dies kann mit einem einfachen PowerShell-Skript erreicht werden. Sie könnten leicht eine schreiben, um dies zu tun, aber ich habe eine in den Einstellungen des Aktualisierungsfensters nach Skriptänderungen gefunden :

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

Zusammenfassung

Gehen Sie wie folgt vor, um eine Benutzerumgebungsvariable mit dem Namen "FOO" zu löschen und die Änderung in den Prozessen zu berücksichtigen, die Sie anschließend starten.

  1. Speichern Sie das PowerShell-Skript in einer Datei (wir nennen es updateenv.ps1).
  2. Führen Sie dies über die Befehlszeile aus: reg delete "HKCU \ Environment" / v FOO / f
  3. Führen Sie updateenv.ps1 aus.
  4. Schließen Sie die Eingabeaufforderung und öffnen Sie sie erneut. Sie werden feststellen, dass die Umgebungsvariable nicht mehr definiert ist.

Beachten Sie, dass Sie wahrscheinlich Ihre PowerShell-Einstellungen aktualisieren müssen, damit Sie dieses Skript ausführen können. Ich lasse dies jedoch als Google-Fu-Übung für Sie.

Jamie
quelle
Gibt es einen bestimmten Grund, warum Sie nicht empfehlen, den Explorer zu beenden und neu zu starten? Das mache ich die ganze Zeit.
Prometheus
Nun, es gibt zwei, die zuerst in den Sinn kommen. Das erste ist, dass Force-Killing-Prozesse Speicherlecks verursachen können. Ja, Prozesse sollten Sandboxen sein, aber selbst der Windows Task-Manager warnt Sie davor, dies leichtfertig zu tun. Der andere persönlichere Grund ist meine Zwangsstörung. Wenn Sie den Explorer beenden und neu starten, werden alle Symbole in der Taskleiste, einschließlich der Duplikate, wenn Sie auf eines klicken, neu angeordnet. Ich möchte, dass meine Symbole in der Reihenfolge bleiben, in der ich die Dinge geöffnet habe.
Jamie
1
Beeindruckend. Der magische Befehl, nach dem ich gesucht habe, verhält sich wie source .bashrc(oder seine Cousins) in Windows. Dies steht für mich ganz oben in der Zeile "Verweis auf diese".
bballdave025
18

In PowerShell können Sie die .NET- [System.Environment]::SetEnvironmentVariable()Methode verwenden:

  • So entfernen Sie eine Benutzerumgebungsvariable mit dem Namen FOO:

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

Beachten Sie, dass dies $nullverwendet wird, um die Absicht , die Variable zu entfernen , besser zu signalisieren. Technisch gesehen entspricht dies jedoch ''in diesem Fall der Übergabe .

  • So entfernen Sie a Systemumgebungsvariable (auf Maschinenebene) mit dem NamenFOO- Erhöhung erforderlich (muss als Administrator ausgeführt werden):

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

Neben der schnelleren Ausführung der Vorteil gegenüber der reg.exe-basierten Methode dass andere Anwendungen über eine WM_SETTINGCHANGENachricht über die Änderung informiert werden (obwohl nicht alle Anwendungen diese Nachricht abhören).

mklement0
quelle
2
Dies ist die beste Antwort hier.
James
1
Diese Methode vermeidet einen Neustart. Was für eine elegante Lösung!
Jyao
13

Ich stimme CupawnTae zu .

SET ist nicht nützlich für Änderungen an der Master-Umgebung.

Zu Ihrer Information: Systemvariablen sind in HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment (viel länger als Benutzervariablen).

Der vollständige Befehl für eine Systemvariable mit dem Namen FOOBAR lautet daher:

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

(Beachten Sie die Anführungszeichen, die für die Bearbeitung des Leerzeichens erforderlich sind.)

Es ist schade das setx Befehl keine Löschsyntax unterstützt. :((

PS: Verantwortungsbewusst verwenden - Wenn Sie Ihre Pfadvariable töten, beschuldigen Sie mich nicht!

DougWare
quelle
@CMCDragonkai, das in der ursprünglichen Frage ausdrücklich erwähnt wird - der Registrierungseintrag wird nicht entfernt, sondern nur gelöscht. Die eigentliche Frage ist, wie man es aus der Registrierung entfernt
CupawnTae
1
Ich möchte nur hinzufügen, dass Sie cmd möglicherweise neu starten / aktualisieren müssen, bevor dies wirksam wird.
Jiggunjer
@ Jiggunjer, Wie aktualisiere ich?
Pacerier
@ Pacerier öffnen Sie einfach ein neues Terminal.
Jiggunjer
11

Der Befehl in DougWares Antwort funktionierte nicht, aber dies tat:

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

Die Verknüpfung HKLMkann für verwendet werden HKEY_LOCAL_MACHINE.

user4297498
quelle
1
Außerdem befinden sich die Benutzerumgebungsvariablen unter "HKCU \ Environment"
tzrlk
1
@Tzrlk, Was ist der Grund für die Nichtübereinstimmung? Warum ist es dort nicht in HKLM \ Environment?
Pacerier
@Pacerier: Ich habe keine Ahnung, warum sie an so völlig getrennten Orten abgelegt werden. Wenn Sie jedoch sicherstellen möchten, dass Sie entweder beide System- oder / und Benutzervariablen entfernt haben, ist es hilfreich zu wissen, dass sie sich an völlig unterschiedlichen Orten befinden setzt.
Tzrlk
2
@Tzrlk, Muss wieder ein verschraubtes Design auf der Windows-Seite sein.
Pacerier
4

Löschen ohne Neustart

Die Frage des OP wurde in der Tat ausführlich beantwortet, einschließlich der Frage, wie ein Neustart durch Powershell, VBScript oder Ihren Namen vermieden werden kann.

Wenn Sie sich jedoch nur an cmd-Befehle halten müssen und nicht den Luxus haben, Powershell oder VBScript aufrufen zu können, können Sie den folgenden Ansatz verwenden:

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

Die Magie hier ist also, dass Sie durch die Verwendung von "setx", um einer nicht benötigten Variablen etwas zuzuweisen (in meinem Beispiel DUMMY), Explorer.exe zwingen, die Variablen aus der Registrierung erneut zu lesen, ohne Powershell zu benötigen. Sie bereinigen dann diesen Dummy, und obwohl dieser noch eine Weile in der Explorer-Umgebung bleibt, wird er wahrscheinlich niemandem schaden.

Oder wenn Sie nach dem Löschen von Variablen neue festlegen müssen, benötigen Sie nicht einmal einen Dummy. Wenn Sie nur SETX verwenden, um die neuen Variablen festzulegen, werden diejenigen, die Sie gerade entfernt haben, automatisch aus allen neuen cmd-Aufgaben gelöscht, die möglicherweise gestartet werden.

Hintergrundinformationen: Ich habe diesen Ansatz gerade erfolgreich verwendet, um eine Reihe von Benutzervariablen durch gleichnamige Systemvariablen auf allen Computern in meinem Job zu ersetzen, indem ich ein vorhandenes cmd-Skript geändert habe. Es gibt zu viele Computer, um dies manuell zu tun, und es war auch nicht praktisch, zusätzliche Powershell- oder VBScripts auf alle zu kopieren. Der Grund, warum ich den Benutzer dringend durch Systemvariablen ersetzen musste, war, dass Benutzervariablen in Roaming-Profilen synchronisiert wurden (ich habe nicht darüber nachgedacht), sodass mehrere Computer, die dieselbe Windows-Anmeldung verwenden, aber unterschiedliche Werte benötigen, verwechselt wurden.

Ronny D'Hoore
quelle
3
setx FOOBAR ""

bewirkt nur, dass der Wert von FOOBAR eine Nullzeichenfolge ist. (Obwohl es mit dem setBefehl mit dem "" angezeigt wird, ist die Zeichenfolge möglicherweise in doppelten Anführungszeichen.)

Ich benutzte:

set FOOBAR=

und dann wurde FOOBAR nicht mehr im Befehl set aufgeführt. (Abmelden war nicht erforderlich.)

Windows 7 32-Bit, über die Eingabeaufforderung, Nicht-Administrator ist das, was ich verwendet habe. (Nicht cmd oder Windows+ R, was möglicherweise anders ist.)

Übrigens habe ich die Variable, die ich erstellt habe, nirgendwo in der Registrierung gesehen, nachdem ich sie erstellt habe. Ich verwende RegEdit nicht als Administrator.

PReinie
quelle
1

Sie können auch ein kleines VBScript- Skript erstellen :

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

Dann nenne es wie %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.

Der Nachteil ist, dass Sie ein zusätzliches Skript benötigen, aber keinen Neustart benötigen.

Wernfried Domscheit
quelle