Linha de comandos para remover uma variável de ambiente da configuração no nível do SO

182

Windows tem o setxcomando:

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

Então você pode definir uma variável como esta:

setx FOOBAR 1

E você pode limpar o valor assim:

setx FOOBAR ""

No entanto, a variável não é removida. Ele permanece no registro:

foobar

Então, como você realmente removeria a variável?

Peter Mortensen
fonte
3
setx apenas define a variável. Você está apenas apagando com essa linha.
Fox Wilson
1
veja também stackoverflow.com/questions/1472722/…
Brian Burns
Como demorei bastante para cavar, consulte também superuser.com/q/297947/46834 para obter opções que não são da linha de comando.
Gary

Respostas:

217

Para remover a variável do ambiente atual ( não permanentemente):

set FOOBAR=

Para remover permanentemente a variável do ambiente do usuário (que é o local padrão setx):

REG delete HKCU\Environment /F /V FOOBAR

Se a variável estiver configurada no ambiente do sistema (por exemplo, se você a configurou originalmente setx /M), como administrador, execute:

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

Nota: Os REGcomandos acima não afetarão nenhum processo existente (e alguns novos processos extraídos de processos existentes); portanto, se é importante que a alteração entre em vigor imediatamente, a coisa mais fácil e segura a fazer é sair e voltar ou reinicie. Se essa não é uma opção ou você deseja ir mais fundo, algumas das outras respostas aqui têm ótimas sugestões que podem se adequar ao seu caso de uso.

CupawnTae
fonte
1
Esta solução parece não funcionar - ou estou entendendo mal algo básico. Eu faço setx JUNK Hello. Abra um novo cmd. Digite echo %JUNK%e obtenha Hello. Então eu faço REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V JUNKe confirmo que o valor foi retirado do registro. Abro novo cmd e digite echo %JUNK%e ainda recebo Hello. A busca no registro não mostra presença de 'JUNK'. Por favor, não me diga que você precisa reiniciar!
caasjj
Obrigado pela resposta. Estou abrindo uma nova janela de comando no menu Iniciar. Eu tentei ambas as versões do comando. De fato, a primeira vez que digito o usercomando environment, ele é bem-sucedido. Então, quando redigito o comando que recebo The system was unable to find the specified registry or key value. Além disso, uma pesquisa global JUNKno registro com regeditnada aparece. Ainda assim, quando abro uma nova janela de comando (via Iniciar / acessórios ou cmd.exe em Executar) e digito echo %JUNK%, o valor ainda está lá!
caasjj
1
Ah! O que você acha que o racional é para isso? Eu sempre evito administrar o máximo possível - educação UNIX / BSD / Linux. Agradece um mil pela impressionante diligência. 1
caasjj
4
talvez seja apenas semântica, mas a exclusão (do registro) entra em vigor imediatamente. O ambiente não é reinicializado a partir do registro até você efetuar login novamente. Você pode combinar os 2 comandos para removê-lo do ambiente atual (que o removerá da SETlista para o próximo shell do cmd) e, em seguida, removê-lo do registro, por exemplo:SETX FOOBAR "" & REG delete HKCU\Environment /F /V FOOBAR
Luke
1
O motivo pelo qual o ambiente não parece ser atualizado sem a reinicialização é porque o explorer.exe não sabe que foi atualizado. Veja minha resposta para obter explicações e soluções completas.
187 Jamie
72

Para remover a variável da sessão de comando atual sem removê-la permanentemente, use o setcomando interno regular - basta colocar nada após o sinal de igual:

set FOOBAR=

Para confirmar, execute setsem argumentos e verifique o ambiente atual. A variável deve estar ausente da lista completamente.

Nota : isso removerá apenas a variável do ambiente atual - não persistirá a alteração no registro. Quando um novo processo de comando é iniciado, a variável volta.

Brian Kelly
fonte
77
Definitivamente, NÃO é a resposta, e acho perturbador o número de votos. Isso é efetivo apenas para a sessão de comando atual. Acione uma nova janela de comando e o var está de volta.
joescii
6
@joescii Você acha isso surpreendente? Isso respondeu à pergunta no título da pergunta. Então, obviamente, o título da pergunta precisava ser mais específico.
Oberlies
10
@oberlies Não concordo que ele responda à pergunta no título, porque isso NÃO funciona no nível do sistema operacional, mas apenas na janela de comando atual. Em segundo lugar, seu argumento sugere que a parte dos detalhes da pergunta é irrelevante.
21119 joelii Jan
3
Infelizmente, a edição parece não ter funcionado - ainda está sendo votada. Eu acho que as pessoas acham útil, mesmo que não responda à pergunta real, caso em que talvez mereça votos positivos (não é?). Pelo menos, não está marcado como aceito, o que seria enganoso.
CupawnTae
3
Eu devo comentar por que eu votei mal. Obviamente, porque isso funciona apenas na sessão atual.
Ian Grainger
22

Isso foi abordado um pouco, mas há uma informação crucial que está faltando. Felizmente, posso ajudar a esclarecer como isso funciona e dar algum alívio aos viajantes cansados. :-)

Excluir do processo atual

Obviamente, todo mundo sabe que você apenas faz isso para excluir uma variável de ambiente do seu processo atual:

set FOO=

Exclusão persistente

Existem dois conjuntos de variáveis ​​de ambiente, em todo o sistema e usuário.

Excluir variável de ambiente do usuário:

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

Excluir variável de ambiente em todo o sistema:

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

Aplicar valor sem reinicializar

Aqui está a informação mágica que está faltando! Você está se perguntando por que, depois de fazer isso, quando você inicia uma nova janela de comando, a variável de ambiente ainda está lá. O motivo é que o explorer.exe não atualizou seu ambiente. Quando um processo inicia outro, o novo processo herda o ambiente do processo que o iniciou.

Existem duas maneiras de corrigir isso sem reiniciar. A maneira mais bruta é matar o processo explorer.exe e iniciá-lo novamente. Você pode fazer isso no Gerenciador de tarefas . Eu não recomendo este método, no entanto.

A outra maneira é dizer ao explorer.exe que o ambiente mudou e que ele deve relê-lo. Isso é feito transmitindo uma mensagem do Windows (WM_SETTINGCHANGE). Isso pode ser realizado com um script simples do PowerShell. Você pode escrever facilmente um para fazer isso, mas eu encontrei um nas Configurações da Janela de Atualização Após Alterações no 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);

Resumo

Portanto, para excluir uma variável de ambiente do usuário denominada "FOO" e ter a alteração refletida nos processos iniciados posteriormente, faça o seguinte.

  1. Salve o script do PowerShell em um arquivo (vamos chamá-lo de updateenv.ps1).
  2. Faça isso na linha de comando: reg delete "HKCU \ Environment" / v FOO / f
  3. Execute updateenv.ps1.
  4. Feche e reabra o prompt de comando e você verá que a variável de ambiente não está mais definida.

Observe que você provavelmente precisará atualizar as configurações do PowerShell para permitir a execução desse script, mas deixarei isso como um exercício do Google-fu para você.

Jamie
fonte
Existe algum motivo específico para você não recomendar matar e reiniciar o explorer? Eu faço isso o tempo todo.
Prometheus
Bem, há dois que primeiro vêm à mente. A primeira é que os processos de eliminação de força podem causar vazamentos de memória. Sim, os processos devem ser caixas de areia, mas mesmo o Gerenciador de Tarefas do Windows avisa para você não fazer isso de ânimo leve. A outra razão mais pessoal é o meu TOC. Quando você mata e reinicia o Explorer, todos os seus ícones na barra de tarefas, incluindo as duplicatas quando você clica em um, são reorganizados. Eu gosto de meus ícones para ficar na ordem em que eu abri as coisas.
Jamie
1
Uau. O comando mágico que eu estou procurando que age como source .bashrc(ou seus primos) no Windows. Isso vai para o topo da linha "consulte-o" para mim.
precisa saber é o seguinte
18

No PowerShell, você pode usar o [System.Environment]::SetEnvironmentVariable()método .NET :

  • Para remover uma variável de ambiente do usuário denominada FOO:

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

Observe que $nullé usado para sinalizar melhor a intenção de remover a variável, embora tecnicamente seja efetivamente o mesmo que passar ''neste caso.

  • Para remover uma variável de ambiente do sistema (no nível da máquina) denominada FOO- requer elevação (deve ser executada como administrador):

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

Além da execução mais rápida, a vantagem sobre o reg.exemétodo baseado é que outros aplicativos são notificados da alteração por meio de uma WM_SETTINGCHANGEmensagem (embora nem todos os aplicativos escutem essa mensagem).

mklement0
fonte
2
Esta é a melhor resposta aqui.
James James
1
Este método evita a necessidade de reinicialização. Que solução elegante!
jyao
13

Eu concordo com CupawnTae .

SET não é útil para alterações no ambiente principal.

FYI: As variáveis ​​do sistema estão dentro HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment(muito mais que as variáveis do usuário).

O comando completo para uma var do sistema chamada FOOBAR é, portanto:

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

(Observe as aspas necessárias para lidar com o espaço.)

É uma pena que o setxcomando não suporte uma sintaxe de exclusão. :(

PS: Use com responsabilidade - Se você matar sua variável de caminho, não me culpe!

DougWare
fonte
O @CMCDragonkai mencionado explicitamente na pergunta original - não remove a entrada do registro, apenas a apaga. Pergunta real é como removê-lo a partir do registro
CupawnTae
1
Eu apenas acrescentaria que você pode precisar reiniciar / atualizar o cmd antes que isso entre em vigor.
jiggunjer
@jiggunjer, Como atualizar?
Pacerier 29/07
O @Pacerier acabou de abrir um novo terminal.
31517 jiggunjer
11

O comando na resposta do DougWare não funcionou, mas o seguinte:

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

O atalho HKLMpode ser usado para HKEY_LOCAL_MACHINE.

user4297498
fonte
1
Além disso, as variáveis ​​de ambiente do usuário estão em "HKCU \ Environment"
tzrlk
1
@Tzrlk, Qual o motivo da incompatibilidade? Por que não está no HKLM \ Environment lá?
Pacerier 29/07
@Pacerier: Eu não tenho idéia do por que eles são colocados em locais completamente separados, mas se você quiser ter certeza de que removeu as variáveis ​​do sistema ou do usuário, ajuda a saber que elas são completamente diferentes lugares.
tzrlk
2
@Tzrlk, deve haver algum design parafusado no lado do Windows novamente.
Pacerier 6/08/17
4

Excluir sem reiniciar

A pergunta do OP realmente foi respondida extensivamente, incluindo como evitar a reinicialização por meio do powershell, vbscript ou qualquer outro nome.

No entanto, se você precisar manter apenas os comandos cmd e não puder se chamar PowerShell ou Vbscript, poderá usar a seguinte abordagem:

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

Portanto, a mágica aqui é que, usando "setx" para atribuir algo a uma variável que você não precisa (no meu exemplo DUMMY), você força o Explorer.exe a reler as variáveis ​​do registro, sem precisar do PowerShell. Em seguida, você limpa esse manequim e, mesmo que ele fique no ambiente do Explorer por mais algum tempo, provavelmente não fará mal a ninguém.

Ou se, após excluir as variáveis, você precisar definir novas, você nem precisará de nenhum manequim. O simples uso do SETX para definir as novas variáveis ​​limpará automaticamente as que você acabou de remover de quaisquer novas tarefas de cmd que possam começar.

Informações básicas: usei essa abordagem com êxito para substituir um conjunto de variáveis ​​de usuário por variáveis ​​de sistema com o mesmo nome em todos os computadores do meu trabalho, modificando um script cmd existente. Existem computadores demais para fazê-lo manualmente, nem era prático copiar um powershell ou vbscripts extra para todos eles. O motivo pelo qual eu precisava urgentemente substituir o usuário por variáveis ​​do sistema era que as variáveis ​​do usuário eram sincronizadas nos perfis de roaming (não pensamos nisso), então várias máquinas usando o mesmo login do Windows, mas precisando de valores diferentes, se misturaram.

Ronny D'Hoore
fonte
3
setx FOOBAR ""

apenas faz com que o valor de FOOBAR seja uma sequência nula. (Embora seja exibido com o setcomando com "", talvez seja a aspas duplas).

Eu usei:

set FOOBAR=

e, em seguida, FOOBAR não estava mais listado no comando set. (O logoff não era necessário.)

Windows 7 de 32 bits, usando o prompt de comando, não administrador. (Não cmd ou Windows+ R, que pode ser diferente.)

BTW, eu não vi a variável que eu criei em nenhum lugar no registro depois que eu a criei. Estou usando o RegEdit não como administrador.

PReinie
fonte
1

Você também pode criar um pequeno script VBScript :

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

Então chame assim %windir%\System32\cscript.exe //Nologo "script_name.vbs" FOOBAR.

A desvantagem é que você precisa de um script extra, mas não requer uma reinicialização.

Wernfried Domscheit
fonte