Командний рядок для видалення змінної середовища з конфігурації рівня ОС


182

У Windows є setxкоманда:

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

Таким чином, ви можете встановити таку змінну:

setx FOOBAR 1

І ви можете очистити таке значення, як це:

setx FOOBAR ""

Однак змінна не видаляється. Він залишається в реєстрі:

foobar

То як би ви насправді видалили змінну?


3
setx просто встановлює змінну. Ви просто вирівнюєте це рядком.
Фокс Вілсон


Оскільки у мене знадобилася велика кількість копання, також перегляньте superuser.com/q/297947/46834 про параметри не командного рядка.
гарі

Відповіді:


217

Щоб видалити змінну з поточного середовища ( не назавжди):

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 / аксесуари, або cmd.exe в Run) і ввожу echo %JUNK%, значення все ще є!
caasjj

1
Ах! Що ви гадаєте, раціональне для цього ?? Я завжди максимально уникаю адміністратора - виховання UNIX / BSD / Linux. Дякую міл за дивовижний старанність. +1
caasjj

4
можливо, це просто семантика, але видалення (з реєстру) набирає чинності негайно. Середовище не повторно ініціалізується з реєстру, поки ви знову не ввійдете в систему. Ви можете об'єднати дві команди, щоб вилучити її з поточного середовища (що видалить її зі SETсписку для наступної оболонки cmd), а потім видалити її з реєстру, наприклад:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Лука

1
Причина, що середовище не оновлюється без перезавантаження, полягає в тому, що explorer.exe не знає, що оновлено. Дивіться мою відповідь для повного пояснення та рішення.
Джеймі

72

Щоб видалити змінну з поточного сеансу команд, не видаляючи її назавжди, використовуйте звичайну вбудовану setкоманду - просто не кладіть нічого після знаку рівності:

set FOOBAR=

Для підтвердження запустіть setбез аргументів і перевірте поточне середовище. Змінна повинна повністю відсутня у списку.

Примітка . Це видалить змінну лише з поточного середовища - вона не збереже зміни в реєстрі. Коли буде запущений новий процес командування, змінна повернеться.


77
Це, безумовно, НЕ відповідь, і мені здається тривожним, що так багато голосів. Це ефективно лише для поточного сеансу командування. Створіть нове вікно команд, і var повернеться.
joescii

6
@joescii Вас це дивно? Це відповіло на запитання у назві питання. Тож очевидно, що питання питання повинно бути більш конкретним.
oberlies

10
@oberlies Я не погоджуюся з тим, що він відповідає на питання в заголовку, оскільки це НЕ працює на рівні ОС, а лише у поточному вікні команди. По-друге, ваша думка говорить про те, що детальна частина питання не має значення.
joescii

3
@oberlies, на жаль, редакція, схоже, не зробила трюк - вона все ще отримує результати. Я думаю, що люди вважають його корисним, навіть якщо він не відповідає на власне питання, і, можливо, він заслуговує на оновлення (чи не так?). Принаймні це не позначено як прийняте, що було б оманливим.
CupawnTae

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 не оновлював своє середовище. Коли один процес запускає інший, новий процес успадковує середовище від процесу, який його запустив.

Є два способи виправити це без перезавантаження. Найбільш грубий спосіб - це вбити процес explor.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-фу.


Чи є якась конкретна причина, яку ви не рекомендуєте вбивати та перезапускати провідник? Я роблю це постійно.
Прометей

Ну, є два, які першими приходять на думку. Перший полягає в тому, що процеси вбивства можуть призвести до витоку пам'яті. Так, процеси повинні бути пісочницями, але навіть менеджер завдань Windows попереджає вас не робити цього злегка. Інша більш особиста причина - мій OCD. Коли ви вбиваєте та перезавантажуєте Провідник, всі ваші піктограми вниз на панелі завдань, включаючи дублікати при натисканні на один, переставляються. Мені подобається, щоб мої іконки залишалися в порядку, в якому я відкрив речі.
Джеймі,

1
Ого. Чарівна команда, яку я шукав, діє як source .bashrc(або її двоюрідні брати) у Windows. Це стосується вершини рядка "звернутися до цього" для мене.
bballdave025

18

У PowerShell ви можете використовувати [System.Environment]::SetEnvironmentVariable()метод .NET :

  • Щоб видалити змінну середовища користувача з назвою FOO:

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

Зауважте, що $nullвикористовується для кращого сигналу про намір видалити змінну, хоча технічно це фактично те саме, що і передача ''в цьому випадку.

  • Щоб видалити систему (машина рівня) змінна середовища з ім'ям FOO- вимагає піднесення (повинен бути запущений від імені адміністратора):

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

Окрім швидшого виконання, перевага перед reg.exeметодом , що базується, полягає в тому, що інші програми повідомляються про зміни за допомогою WM_SETTINGCHANGEповідомлення (хоча не всі програми слухають це повідомлення).


2
Тут найкраща відповідь.
Джеймс

1
Цей метод дозволяє уникнути необхідності перезавантаження. Яке елегантне рішення!
цзяо

13

Я згоден з CupawnTae .

SET не є корисним для змін в основному середовищі.

FYI: Змінні системи є HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment(значно довше, ніж користувачі).

Повна команда для системного var з назвою FOOBAR:

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

(Зверніть увагу на лапки, необхідні для обробки місця.)

Це дуже погано, що setxкоманда не підтримує синтаксис видалення. :(

PS: Використовуйте відповідально - Якщо ви вб'єте змінну свого шляху, не звинувачуйте мене!


@CMCDragonkai, про який явно йдеться в оригінальному запитанні - він не видаляє запис реєстру, він просто запорожцює. Актуальне питання - як його видалити з реєстру
CupawnTae

1
Я просто додам, що вам може знадобитися перезапустити / оновити cmd, перш ніж це набере чинності.
jiggunjer

@jiggunjer, як оновити?
Pacerier

@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 \ Environment?
Pacerier

@Pacerier: Я поняття не маю, чому вони розміщують їх у таких абсолютно окремих місцях, але якщо ви хочете переконатися, що ви видалили або / або системні або / та змінні користувача, це допомагає знати, що вони знаходяться в абсолютно інших місця.
tzrlk

2
@Tzrlk, Мабуть, знову буде якийсь накручений дизайн на стороні Windows.
Pacerier

4

Видалити без перезавантаження

На питання ОП дійсно отримали відповіді широко, зокрема про те, як уникнути перезавантаження через повноваження, 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 перечитувати змінні з реєстру, не потребуючи повноважень. Потім ви прибираєте цю манекен, і хоча ця залишиться ще довше в середовищі Провідника, вона, мабуть, нікому не зашкодить.

Або якщо після видалення змінних вам потрібно встановити нові, то вам навіть не потрібна фіктивна. Використання SETX для встановлення нових змінних автоматично очистить ті, які ви тільки що видалили, з будь-яких нових завдань cmd, які можуть почати роботу.

Довідкова інформація: Я просто використовував цей підхід успішно, щоб замінити набір змінних користувачів на системні змінні з тим самим іменем на всіх комп’ютерах у мене на роботі, змінивши існуючий сценарій cmd. Занадто багато комп'ютерів, щоб зробити це вручну, і не було практично копіювати додаткові оболонки повноважень або vbscripts на всі з них. Причиною, що мені терміново потрібно було замінити користувача системними змінними, було те, що користувацькі змінні синхронізуються в роумінгових профілях (про це не думали), тому кілька машин, що використовують один і той же вхід у Windows, але потребують різних значень, змішалися.


3
setx FOOBAR ""

просто викликає значення FOOBAR як нульовий рядок. (Хоча, це показує за допомогою setкоманди "", тому, можливо, подвійні лапки є рядком.)

Я використав:

set FOOBAR=

і тоді FOOBAR більше не вказаний у команді set. (Вихід не потрібен.)

Windows 7 32 біт, використовуючи командний рядок, не адміністратор - це те, що я використовував. (Не cmd або Windows+ R, що може бути різним.)

BTW, я не бачив змінної, яку я створив ніде в реєстрі після того, як я її створив. Я використовую 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.

Недоліком є ​​те, що вам потрібен додатковий сценарій, але він не потребує перезавантаження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.