Existe um comando para as variáveis ??de ambiente de atualização de prompt de comando no Windows?

StackOverflow https://stackoverflow.com/questions/171588

Pergunta

Se eu alterar ou adicionar uma variável de ambiente que eu tenho que reiniciar o prompt de comando. Existe um comando que eu poderia executar que faria isso sem reiniciar CMD?

Foi útil?

Solução

Você pode capturar as variáveis ??de ambiente do sistema com um script vbs, mas você precisa de um script bat para realmente mudar as variáveis ??de ambiente atuais, por isso esta é uma solução combinada.

Crie um arquivo chamado resetvars.vbs contendo este código, e guardá-lo no caminho:

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("System")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
path = oEnv("PATH")

set oEnv=oShell.Environment("User")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next

path = path & ";" & oEnv("PATH")
oFile.WriteLine("SET PATH=" & path)
oFile.Close

criar outro nome de arquivo resetvars.bat contendo este código, mesmo local:

@echo off
%~dp0resetvars.vbs
call "%TEMP%\resetvars.bat"

resetvars.bat Quando você quiser atualizar as variáveis ??de ambiente, basta executar


Apologética :

Os dois principais problemas que eu tinha vindo acima com esta solução foram

a. eu não poderia encontrar uma maneira simples de variáveis ??de ambiente exportação de uma volta vbs script para o prompt de comando, e

b. a variável de ambiente PATH é uma concatenação do usuário e as variáveis ??PATH do sistema.

Eu não tenho certeza que a regra geral é para conflitantes variáveis ??entre usuário e do sistema, então eu eleitos para tornar o sistema de utilizador substituição, exceto na variável PATH que é tratado especificamente.

Eu uso os vbs estranhas + bat + mecanismo de morcego temporária para o trabalho em torno do problema de exportar variáveis ??de VBS.

Nota :. Este script faz variáveis ??não excluir

Este provavelmente pode ser melhorado.

ADICIONADO

Se você precisa exportar o ambiente de uma janela cmd para outro, use este script (vamos chamá-lo exportvars.vbs):

Set oShell = WScript.CreateObject("WScript.Shell")
filename = oShell.ExpandEnvironmentStrings("%TEMP%\resetvars.bat")
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set oFile = objFileSystem.CreateTextFile(filename, TRUE)

set oEnv=oShell.Environment("Process")
for each sitem in oEnv 
    oFile.WriteLine("SET " & sitem)
next
oFile.Close

Executar exportvars.vbs na janela que deseja exportar , em seguida, mudar para a janela que deseja exportar para , e digite:

"%TEMP%\resetvars.bat"

Outras dicas

Aqui está o que os usos Chocolatey.

https://github.com/ chocolatey / choco / blob / master / src / chocolatey.resources / redirecionamentos / RefreshEnv.cmd

@echo off
::
:: RefreshEnv.cmd
::
:: Batch file to read environment variables from registry and
:: set session variables to these values.
::
:: With this batch file, there should be no need to reload command
:: environment every time you want environment changes to propagate

echo | set /p dummy="Reading environment variables from registry. Please wait... "

goto main

:: Set one environment variable from registry key
:SetFromReg
    "%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > "%TEMP%\_envset.tmp" 2>NUL
    for /f "usebackq skip=2 tokens=2,*" %%A IN ("%TEMP%\_envset.tmp") do (
        echo/set %~3=%%B
    )
    goto :EOF

:: Get a list of environment variables from registry
:GetRegEnv
    "%WinDir%\System32\Reg" QUERY "%~1" > "%TEMP%\_envget.tmp"
    for /f "usebackq skip=2" %%A IN ("%TEMP%\_envget.tmp") do (
        if /I not "%%~A"=="Path" (
            call :SetFromReg "%~1" "%%~A" "%%~A"
        )
    )
    goto :EOF

:main
    echo/@echo off >"%TEMP%\_env.cmd"

    :: Slowly generating final file
    call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> "%TEMP%\_env.cmd"
    call :GetRegEnv "HKCU\Environment">>"%TEMP%\_env.cmd" >> "%TEMP%\_env.cmd"

    :: Special handling for PATH - mix both User and System
    call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> "%TEMP%\_env.cmd"
    call :SetFromReg "HKCU\Environment" Path Path_HKCU >> "%TEMP%\_env.cmd"

    :: Caution: do not insert space-chars before >> redirection sign
    echo/set Path=%%Path_HKLM%%;%%Path_HKCU%% >> "%TEMP%\_env.cmd"

    :: Cleanup
    del /f /q "%TEMP%\_envset.tmp" 2>nul
    del /f /q "%TEMP%\_envget.tmp" 2>nul

    :: Set these variables
    call "%TEMP%\_env.cmd"

    echo | set /p dummy="Done"
    echo .

Pelo projeto não é um construído em mecanismo para Windows para propagar um ambiente variável add / Alterar / remover para um cmd.exe já em execução, ou de outro cmd.exe ou a partir de "My computador -> Propriedades -> Configurações avançadas -.> Variáveis ??de ambiente"

Se você modificar ou adicionar um novo fora do ambiente variável do escopo de um comando de abertura existente prompt de você ou necessidade de reiniciar o prompt de comando, ou, adicionar manualmente usando SET no comando existente pronta.

O últimos shows resposta aceita um parcial de trabalho-around por atualizar manualmente todas as variáveis ??de ambiente em um script. As alças de script O caso de uso de mudança de variáveis ??de ambiente globalmente em "Meu Computador ... Variáveis ??de Ambiente", mas se uma variável de ambiente é alterado em um cmd.exe o script não irá propagar-lo para outro cmd.exe em execução.

No windows 7/8/10 você pode instalar Chocolatey que tem um script para este construído em.

Depois de instalar Chocolatey, basta digitar "refreshenv" sem aspas.

Isso funciona em Windows 7: SET PATH=%PATH%;C:\CmdShortcuts

testados digitando echo% PATH% e funcionou, tudo bem. também definir se você abrir uma nova cmd, não há necessidade para aqueles traquinas reinicia mais:)

me deparei com esta resposta antes de eventualmente encontrar uma solução mais fácil.

Simplesmente reiniciar explorer.exe no Gerenciador de tarefas.

Eu não testei, mas você também pode precisar de reabrir você prompt de comando.

Crédito para Timo Huovinen aqui: nó não reconhecido, embora instalado com sucesso (se isso te ajudou, por favor, vá dar comentário de crédito deste homem).

Use "setx" e reiniciar cmd prompt de

Há uma ferramenta de linha de comando chamado " setx " para este trabalho. É para leitura e escrita variáveis ??env. As variáveis ??persistem após a janela de comando foi fechada.

"cria ou modifica variáveis ??de ambiente no ambiente do usuário ou do sistema, sem a necessidade de programação ou scripting. A setx comando também recupera os valores das chaves de registro e escreve-los em arquivos de texto."

Nota: variáveis ??criadas ou modificadas por esta ferramenta estará disponível em janelas de comando futuras, mas não na janela de comando atual CMD.exe. Então, você tem que reiniciar.

Se setx está faltando:


Ou modificar o registo

MSDN diz:

Para adicionar ou modificar variáveis ??de ambiente do sistema de programação, add -los para o HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment chave de registro, em seguida, transmitir um WM_SETTINGCHANGE mensagem com lParam set para a string " Ambiente ".

Isso permite que aplicativos, como o shell, para pegar suas atualizações.

Chamar esta função tem trabalhado para mim:

VOID Win32ForceSettingsChange()
{
    DWORD dwReturnValue;
    ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
}

O melhor método que eu vim com foi apenas para fazer uma consulta de registo. Aqui está o meu exemplo.

No meu exemplo eu fiz uma instalação utilizando um arquivo de lote que acrescentou novas variáveis ??de ambiente. Eu precisava fazer coisas com isso assim que a instalação foi concluída, mas foi incapaz de gerar um novo processo com essas novas variáveis. Eu testei desova outra janela explorador e chamado de volta para Cmd.exe e isso funcionou, mas no Vista e Windows 7, o Explorer só funciona como uma única instância e, normalmente, como a pessoa logado. Isso falhar com automação desde que eu preciso meus creds de administrador para fazer coisas independentemente de correr de sistema local ou como um administrador na caixa. A limitação para isso é que ele não lidar com coisas como caminho, isso só trabalhou em variáveis ??de ambiente simples. Isso me permitiu usar um lote para chegar até um diretório (com espaços) e copiar em arquivos executar .EXEs e etc. Isto foi escrito a partir de hoje os recursos podem on stackoverflow.com

lote chamadas Orginal para novo lote:

SDROOT testenvget.cmd (ou qualquer que seja a variável)

@ECHO OFF
setlocal ENABLEEXTENSIONS
set keyname=HKLM\System\CurrentControlSet\Control\Session Manager\Environment
set value=%1
SET ERRKEY=0

REG QUERY "%KEYNAME%" /v "%VALUE%" 2>NUL| FIND /I "%VALUE%"
IF %ERRORLEVEL% EQU 0 (
ECHO The Registry Key Exists 
) ELSE (
SET ERRKEY=1
Echo The Registry Key Does not Exist
)

Echo %ERRKEY%
IF %ERRKEY% EQU 1 GOTO :ERROR

FOR /F "tokens=1-7" %%A IN ('REG QUERY "%KEYNAME%" /v "%VALUE%" 2^>NUL^| FIND /I "%VALUE%"') DO (
ECHO %%A
ECHO %%B
ECHO %%C
ECHO %%D
ECHO %%E
ECHO %%F
ECHO %%G
SET ValueName=%%A
SET ValueType=%%B
SET C1=%%C
SET C2=%%D
SET C3=%%E
SET C4=%%F
SET C5=%%G
)

SET VALUE1=%C1% %C2% %C3% %C4% %C5%
echo The Value of %VALUE% is %C1% %C2% %C3% %C4% %C5%
cd /d "%VALUE1%"
pause
REM **RUN Extra Commands here**
GOTO :EOF

:ERROR
Echo The the Enviroment Variable does not exist.
pause
GOTO :EOF

Além disso, há outro método que eu vim com a partir de várias idéias diferentes. Por favor veja abaixo. Isso basicamente terá a variável de caminho mais novo do registro no entanto, isso irá causar uma série de questões Beacuse a consulta de registro vai dar variáveis ??em si, o que significa todos os lugares há uma variável Isso não vai funcionar, de modo a combater este problema I basicamente dobrar o caminho. Muito nojento. O método mais perfered seria fazer: Set Path =% Path%; C: \ Arquivos de Programas \ Software .... \

Independentemente aqui é o novo arquivo de lote, por favor use cautela.

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
set org=%PATH%
for /f "tokens=2*" %%A in ('REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path ^|FIND /I "Path"') DO (
SET path=%%B
)
SET PATH=%org%;%PATH%
set path

É possível fazer isso, substituindo a tabela de ambiente dentro de si um processo especificado.

Como uma prova de conceito que eu escrevi este aplicativo de exemplo, que acabou de editar um único (conhecidos) variável de ambiente em um processo cmd.exe:

typedef DWORD (__stdcall *NtQueryInformationProcessPtr)(HANDLE, DWORD, PVOID, ULONG, PULONG);

int __cdecl main(int argc, char* argv[])
{
    HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
    NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtDll, "NtQueryInformationProcess");

    int processId = atoi(argv[1]);
    printf("Target PID: %u\n", processId);

    // open the process with read+write access
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 0, processId);
    if(hProcess == NULL)
    {
        printf("Error opening process (%u)\n", GetLastError());
        return 0;
    }

    // find the location of the PEB
    PROCESS_BASIC_INFORMATION pbi = {0};
    NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
    if(status != 0)
    {
        printf("Error ProcessBasicInformation (0x%8X)\n", status);
    }
    printf("PEB: %p\n", pbi.PebBaseAddress);

    // find the process parameters
    char *processParamsOffset = (char*)pbi.PebBaseAddress + 0x20; // hard coded offset for x64 apps
    char *processParameters = NULL;
    if(ReadProcessMemory(hProcess, processParamsOffset, &processParameters, sizeof(processParameters), NULL))
    {
        printf("UserProcessParameters: %p\n", processParameters);
    }
    else
    {
        printf("Error ReadProcessMemory (%u)\n", GetLastError());
    }

    // find the address to the environment table
    char *environmentOffset = processParameters + 0x80; // hard coded offset for x64 apps
    char *environment = NULL;
    ReadProcessMemory(hProcess, environmentOffset, &environment, sizeof(environment), NULL);
    printf("environment: %p\n", environment);

    // copy the environment table into our own memory for scanning
    wchar_t *localEnvBlock = new wchar_t[64*1024];
    ReadProcessMemory(hProcess, environment, localEnvBlock, sizeof(wchar_t)*64*1024, NULL);

    // find the variable to edit
    wchar_t *found = NULL;
    wchar_t *varOffset = localEnvBlock;
    while(varOffset < localEnvBlock + 64*1024)
    {
        if(varOffset[0] == '\0')
        {
            // we reached the end
            break;
        }
        if(wcsncmp(varOffset, L"ENVTEST=", 8) == 0)
        {
            found = varOffset;
            break;
        }
        varOffset += wcslen(varOffset)+1;
    }

    // check to see if we found one
    if(found)
    {
        size_t offset = (found - localEnvBlock) * sizeof(wchar_t);
        printf("Offset: %Iu\n", offset);

        // write a new version (if the size of the value changes then we have to rewrite the entire block)
        if(!WriteProcessMemory(hProcess, environment + offset, L"ENVTEST=def", 12*sizeof(wchar_t), NULL))
        {
            printf("Error WriteProcessMemory (%u)\n", GetLastError());
        }
    }

    // cleanup
    delete[] localEnvBlock;
    CloseHandle(hProcess);

    return 0;
}

Exemplo de saída:

>set ENVTEST=abc

>cppTest.exe 13796
Target PID: 13796
PEB: 000007FFFFFD3000
UserProcessParameters: 00000000004B2F30
environment: 000000000052E700
Offset: 1528

>set ENVTEST
ENVTEST=def

Notas

Esta abordagem também seria limitado a restrições de segurança. Se o alvo é executado em maior elevação ou uma conta mais elevada (como SYSTEM), então não teríamos permissão para editar sua memória.

Se você quiser fazer isso com um aplicativo de 32 bits, os deslocamentos codificados duros acima mudaria para 0x10 e 0x48 respectivamente. Essas compensações podem ser encontrados por despejar os _PEB e _RTL_USER_PROCESS_PARAMETERS estruturas em um depurador (por exemplo, no WinDbg dt _PEB e dt _RTL_USER_PROCESS_PARAMETERS)

Para alterar a prova-de-conceito em um quais são as necessidades do OP, seria apenas enumerar as variáveis ??atuais do sistema e de ambiente do usuário (como documentado por resposta de @ Tsadok) e escrever a tabela ambiente inteiro na memória processo de destino .

Editar: O tamanho do bloco de ambiente também é armazenado na estrutura _RTL_USER_PROCESS_PARAMETERS, mas a memória é alocada na pilha de processo. Assim, a partir de um processo externo não teríamos a capacidade de redimensioná-la e torná-lo maior. Eu brinquei com o uso VirtualAllocEx para alocar memória adicional no processo de destino para o armazenamento ambiente, e foi capaz de definir e ler uma tabela totalmente novo. Infelizmente qualquer tentativa de modificar o ambiente de meios normais vai bater e queimar como o endereço de pontos não mais para a pilha (ele irá travar em RtlSizeHeap).

As variáveis ??de ambiente são mantidos em HKEY_LOCAL_MACHINE \ SYSTEM \ ControlSet \ Control \ Session Manager \ Environment.

Muitos dos vars env úteis, tais como Path, são armazenados como REG_SZ. Há várias maneiras de acessar o registro incluindo REGEDIT:

REGEDIT /E &lt;filename&gt; "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"

A saída começa com números mágicos. Então, para procurá-la com o comando find ele precisa ser digitado e redirecionado: type <filename> | findstr -c:\"Path\"

Então, se você quiser apenas para atualizar a variável de caminho na sua sessão de comando atual com o que está nas propriedades do sistema o seguinte script em lotes funciona bem:

RefreshPath.cmd:

    @echo off

    REM This solution requests elevation in order to read from the registry.

    if exist %temp%\env.reg del %temp%\env.reg /q /f

    REGEDIT /E %temp%\env.reg "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment"

    if not exist %temp%\env.reg (
       echo "Unable to write registry to temp location"
       exit 1
       )

    SETLOCAL EnableDelayedExpansion

    for /f "tokens=1,2* delims==" %%i in ('type %temp%\env.reg ^| findstr -c:\"Path\"=') do (
       set upath=%%~j
       echo !upath:\\=\! >%temp%\newpath
       )

     ENDLOCAL

     for /f "tokens=*" %%i in (%temp%\newpath) do set path=%%i

A coisa confusa pode ser que existem alguns lugares para começar o cmd partir. No meu caso eu corri cmd do Windows Explorer eo ambiente variáveis ??não mudar , enquanto ao iniciar cmd do "run" (tecla Windows + r) o ambiente variáveis ??foram alteradas .

No meu caso eu só tinha de matam as janelas explorer processo a partir do Gerenciador de tarefas e, em seguida, reiniciá-lo novamente a partir do gerenciador de tarefas .

Uma vez eu fiz isso teve acesso I da nova variável de ambiente a partir de um cmd que foi gerado a partir de Windows Explorer.

Tente abrir um novo prompt de comando como um administrador. Isso funcionou para mim no Windows 10. (Eu sei que esta é uma velha resposta, mas eu tinha que compartilhar isso porque ter que escrever um script VBS apenas para isso é um absurdo).

A maneira mais fácil de adicionar uma variável para o caminho sem reiniciar para a sessão atual é abrir o prompt de comando e digite:

PATH=(VARIABLE);%path%

e pressione digite .

para verificar se sua variável carregado, digite

PATH

e pressione digite . No entanto, a variável será apenas uma parte do caminho até que reinicie.

Reiniciar o explorador fez isso por mim, mas apenas para novos terminais cmd.

O terminal I definir o caminho podia ver a nova variável Path já (no Windows 7).

taskkill /f /im explorer.exe && explorer.exe

Eu uso o seguinte código em meus scripts em lotes:

if not defined MY_ENV_VAR (
    setx MY_ENV_VAR "VALUE" > nul
    set MY_ENV_VAR=VALUE
)
echo %MY_ENV_VAR%

Ao usar o SET depois SETX é possível usar a variável "local" directamente sem reiniciar a janela de comando. E na próxima corrida, será usada a variável de ambiente.

basta reiniciar explorer.exe >> testado em win 8 X64

Eu gostei da abordagem seguida por achocolatada, como postou em resposta covarde anônimo, uma vez que é uma abordagem lote puro. No entanto, ele deixa um arquivo temporário e algumas variáveis ??temporárias em torno de mentir. Eu fiz uma versão mais limpo para mim.

Faça um algum lugar refreshEnv.bat arquivo no seu PATH. Atualizar seu ambiente de consola executando refreshEnv.

@ECHO OFF
REM Source found on https://github.com/DieterDePaepe/windows-scripts
REM Please share any improvements made!

REM Code inspired by http://stackoverflow.com/questions/171588/is-there-a-command-to-refresh-environment-variables-from-the-command-prompt-in-w

IF [%1]==[/?] GOTO :help
IF [%1]==[/help] GOTO :help
IF [%1]==[--help] GOTO :help
IF [%1]==[] GOTO :main

ECHO Unknown command: %1
EXIT /b 1 

:help
ECHO Refresh the environment variables in the console.
ECHO.
ECHO   refreshEnv       Refresh all environment variables.
ECHO   refreshEnv /?        Display this help.
GOTO :EOF

:main
REM Because the environment variables may refer to other variables, we need a 2-step approach.
REM One option is to use delayed variable evaluation, but this forces use of SETLOCAL and
REM may pose problems for files with an '!' in the name.
REM The option used here is to create a temporary batch file that will define all the variables.

REM Check to make sure we don't overwrite an actual file.
IF EXIST %TEMP%\__refreshEnvironment.bat (
  ECHO Environment refresh failed!
  ECHO.
  ECHO This script uses a temporary file "%TEMP%\__refreshEnvironment.bat", which already exists. The script was aborted in order to prevent accidental data loss. Delete this file to enable this script.
  EXIT /b 1
)

REM Read the system environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM Read the user environment variables from the registry.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment`) DO (
  REM /I -> ignore casing, since PATH may also be called Path
  IF /I NOT [%%I]==[PATH] (
    ECHO SET %%I=%%K>>%TEMP%\__refreshEnvironment.bat
  )
)

REM PATH is a special variable: it is automatically merged based on the values in the
REM system and user variables.
REM Read the PATH variable from the system and user environment variables.
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH`) DO (
  ECHO SET PATH=%%K>>%TEMP%\__refreshEnvironment.bat
)
FOR /F "usebackq tokens=1,2,* skip=2" %%I IN (`REG QUERY HKCU\Environment /v PATH`) DO (
  ECHO SET PATH=%%PATH%%;%%K>>%TEMP%\__refreshEnvironment.bat
)

REM Load the variable definitions from our temporary file.
CALL %TEMP%\__refreshEnvironment.bat

REM Clean up after ourselves.
DEL /Q %TEMP%\__refreshEnvironment.bat

ECHO Environment successfully refreshed.

Se se trata de apenas um (ou alguns) específico vars você quer mudar, eu acho que a maneira mais fácil é um Solução : apenas definir em em seu ambiente e em sua atual sessão do console

  • Set irá colocar o var em sua sessão atual
  • SetX vai colocar o var no ambiente, mas não na sua sessão atual

Eu tenho esse script em lotes simples de mudar o meu Maven de Java7 para Java8 (que são ambos env. VARs) A-pasta do lote é no meu PATH var para que eu possa sempre chamar ' J8 ' e dentro do meu console e no ambiente minha JAVA_HOME var é alterado:

j8.bat:

@echo off
set JAVA_HOME=%JAVA_HOME_8%
setx JAVA_HOME "%JAVA_HOME_8%"

Até agora eu encontrar este trabalho melhor e mais fácil. Você provavelmente quer que isso seja em um comando, mas ele simplesmente não existe no Windows ...

Primeiro instale choco:

  • Se usando cmd @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

  • Se usando powershell Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Em seguida, você pode executar refreshenv. Ele funciona tanto em cmd e PowerShell.

Não há nenhuma maneira em linha reta, como disse Kev. Na maioria dos casos, é mais simples para desovar outra caixa CMD. Mais irritante, os programas em execução não estão cientes das mudanças tanto (embora IIRC pode haver uma mensagem de difusão para assistir a ser notificada dessa mudança).

Ele ter sido pior: em versões mais antigas do Windows, você tinha que terminar a sessão inicie novamente a tomar em conta as mudanças ...

Eu uso este script PowerShell para adicionar à PATH variável. Com um pequeno ajuste pode trabalhar no seu caso também eu acredito.

#REQUIRES -Version 3.0

if (-not ("win32.nativemethods" -as [type])) {
    # import sendmessagetimeout from win32
    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

function global:ADD-PATH
{
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)] 
        [string] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $null) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # Get the current search path from the environment keys in the registry.
    $oldPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # See if the new Folder is already in the path.
    if ($oldPath | Select-String -SimpleMatch $Folder){ 
        return 'Folder already within $ENV:PATH' 
    }

    # Set the New Path and add the ; in front
    $newPath=$oldPath+';'+$Folder
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show our results back to the world
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}

function global:REMOVE-PATH {
    [Cmdletbinding()]
    param ( 
        [parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0)]
        [String] $Folder
    )

    # See if a folder variable has been supplied.
    if (!$Folder -or $Folder -eq "" -or $Folder -eq $NULL) { 
        throw 'No Folder Supplied. $ENV:PATH Unchanged'
    }

    # add a leading ";" if missing
    if ($Folder[0] -ne ";") {
        $Folder = ";" + $Folder;
    }

    # Get the Current Search Path from the environment keys in the registry
    $newPath=$(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path

    # Find the value to remove, replace it with $NULL. If it's not found, nothing will change and you get a message.
    if ($newPath -match [regex]::Escape($Folder)) { 
        $newPath=$newPath -replace [regex]::Escape($Folder),$NULL 
    } else { 
        return "The folder you mentioned does not exist in the PATH environment" 
    }

    # Update the Environment Path
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath -ErrorAction Stop

    # Show what we just did
    return 'This is the new PATH content: '+$newPath

    # notify all windows of environment block change
    [win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result)
}


# Use ADD-PATH or REMOVE-PATH accordingly.

#Anything to Add?

#Anything to Remove?

REMOVE-PATH "%_installpath_bin%"

Obrigado por postar esta questão que é bastante interessante, mesmo em 2019 (Na verdade, não é fácil para renovar o cmd shell, pois é uma única instância como mencionado acima), porque renovando variáveis ??de ambiente no Windows permite realizar muitas tarefas de automação sem ter que reiniciar manualmente na linha de comando.

Por exemplo, podemos usar isso para permitir que o software a ser implantado e configurado em um grande número de máquinas que reinstalar regularmente. E devo admitir que ter que reiniciar a linha de comando durante a implantação do nosso software seria muito pouco prático e nos obrigaria a encontrar soluções alternativas que não são necessariamente agradável. Vamos ao nosso problema. Nós proceder da seguinte forma.

1 - Nós temos um script em lotes que por sua vez chama um script powershell como este

[file: task.cmd] .

cmd > powershell.exe -executionpolicy unrestricted -File C:\path_here\refresh.ps1

2 - Depois disso, o script refresh.ps1 renova as variáveis ??de ambiente usando chaves de registro (GetValueNames (), etc.). Em seguida, no mesmo script powershell, só temos de chamar as novas variáveis ??de ambiente disponíveis. Por exemplo, em um caso típico, se acabou de instalar NodeJS antes com cmd usando comandos silenciosos, depois que a função foi chamado, podemos chamar diretamente npm para instalar, na mesma sessão, pacotes específicos como segue.

[file: refresh.ps1]

function Update-Environment {
    $locations = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session  Manager\Environment',
                 'HKCU:\Environment'
    $locations | ForEach-Object {
        $k = Get-Item $_
        $k.GetValueNames() | ForEach-Object {
            $name  = $_
            $value = $k.GetValue($_)

            if ($userLocation -and $name -ieq 'PATH') {
                $env:Path += ";$value"
            } else {

                Set-Item -Path Env:\$name -Value $value
            }
        }
        $userLocation = $true
    }
}
Update-Environment
#Here we can use newly added environment variables like for example npm install.. 
npm install -g create-react-app serve

Uma vez que o script do PowerShell é longo, o script cmd continua com outras tarefas. Agora, uma coisa a ter em mente é que, após a tarefa estiver concluída, cmd ainda não tem acesso às novas variáveis ??de ambiente, mesmo se o script powershell actualiza aqueles em sua própria sessão. É por isso que fazemos todas as tarefas necessárias no script powershell que pode chamar os mesmos comandos como cmd é claro.

Não, eu não penso assim ... você pode configurá-los manualmente embora. Assim, você pode colocá-los em um arquivo de lote ou algo assim.

provavelmente poderia fazer um utilitário / script (se alguém não tem já) que consulta o registro e define o ambiente atual para ser o mesmo

Edit:. Isso só funciona se o ambiente muda você está fazendo é como um resultado da execução de um arquivo de lote

Se um arquivo de lote começa com SETLOCAL então ele vai voltar sempre desvendar ao seu ambiente original em saída, mesmo se você esquecer de chamar ENDLOCAL antes de sair do lote, ou se interrompe inesperadamente.

Quase todos os lotes de arquivos I write começa com SETLOCAL uma vez que na maioria dos casos, eu não quero que os efeitos colaterais de alterações de ambiente para permanecer. Em casos onde eu quero certas mudanças ambiente variáveis ??para propagar fora do arquivo de lote, em seguida, minhas últimas ENDLOCAL parece com isso:

ENDLOCAL & (
  SET RESULT1=%RESULT1%
  SET RESULT2=%RESULT2%
)

Para resolver este eu mudei a variável de ambiente usando tanto setx e set, e depois reiniciado todas as instâncias do explorer.exe. Desta forma, qualquer processo, posteriormente, começou terão a nova variável de ambiente.

O meu script em lotes para fazer isso:

setx /M ENVVAR "NEWVALUE"
set ENVVAR="NEWVALUE"

taskkill /f /IM explorer.exe
start explorer.exe >nul
exit

O problema com esta abordagem é que todas as janelas explorer que estão abertas serão fechadas, o que provavelmente é uma má idéia - Mas veja o post por Kev para saber por que isso é necessário

Ou você pode simplesmente fazê-lo manualmente através

Para visualizar ou ambiente mudança variáveis: o botão direito do mouse em Meu Computador e, em em seguida, clique em Propriedades. Clique na guia Avançado. Clique em Ambiente variáveis. Clique em uma das seguintes opções, para um usuário ou um variável de sistema: Clique em Novo para adicionar um novo nome e valor da variável. Clique uma variável existente e clique em Editar para alterar o nome ou valor. Clique uma variável existente e clique em Excluir para removê-lo. http://support.microsoft.com/kb/310519

variáveis ??ambiente Windows XP

%ALLUSERSPROFILE% (%PROGRAMDATA%)   C:\Documents and Settings\All Users
%APPDATA%   C:\Documents and Settings\{username}\Application Data
%COMPUTERNAME%  {computername}
%COMMONPROGRAMFILES%    C:\Program Files\Common Files
%COMMONPROGRAMFILES(x86)%   C:\Program Files (x86)\Common Files
%COMSPEC%   C:\Windows\System32\cmd.exe
%HOMEDRIVE% C:
%HOMEPATH%  \Documents and Settings\{username}
%LOCALAPPDATA%  Not available
%LOGONSERVER%   \\{domain_logon_server}
%PATH%  C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}
%PATHEXT%   .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.WSF;.WSH
%PROGRAMFILES%  C:\Program Files
%PROGRAMFILES(X86)% C:\Program Files (x86) (only in 64-bit version)
%PROMPT%    Code for current command prompt format. Code is usually $P$G
%SystemDrive%   C:
%SystemRoot%    The Windows directory, usually C:\Windows, formerly C:\WINNT
%TEMP% and %TMP%    C:\Documents and Settings\{username}\Local Settings\Temp
%USERDOMAIN%    {userdomain}
%USERNAME%  {username}
%USERPROFILE%   C:\Documents and Settings\{username}
%WINDIR%    C:\Windows
%PUBLIC%    
%PROGRAMDATA%   Only available in Windows Vista and newer versions
%PSModulePath%  

variáveis ??Windows 7 Ambiente

%ALLUSERSPROFILE% (%PROGRAMDATA%)   C:\ProgramData
%APPDATA%   C:\Users\{username}\AppData\Roaming
%COMPUTERNAME%  {computername}
%COMMONPROGRAMFILES%    C:\Program Files\Common Files
%COMMONPROGRAMFILES(x86)%   C:\Program Files (x86)\Common Files
%COMSPEC%   C:\Windows\System32\cmd.exe
%HOMEDRIVE% C:
%HOMEPATH%  \Users\{username}
%LOCALAPPDATA%  C:\Users\{username}\AppData\Local
%LOGONSERVER%   \\{domain_logon_server}
%PATH%  C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;{plus program paths}
%PATHEXT%   .com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.msc
%PROGRAMFILES%  C:\Program Files
%PROGRAMFILES(X86)% C:\Program Files (x86) (only in 64-bit version)
%PROMPT%    Code for current command prompt format. Code is usually $P$G
%SystemDrive%   C:
%SystemRoot%    C:\Windows
%TEMP% and %TMP%    C:\Users\{username}\AppData\Local\Temp
%USERDOMAIN%    {userdomain}
%USERNAME%  {username}
%USERPROFILE%   C:\Users\{username}
%WINDIR%    C:\Windows
%PUBLIC%    C:\Users\Public
%PROGRAMDATA%   C:\ProgramData
%PSModulePath%  %SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\

http://www.binbert.com/blog/2010/09/default-environment-variable-values-of-windows-7-xp/

espero que isso ajude.

Apenas digite "# -r" (sem aspas # com opção -r) no seu terminal. E está tudo pronto para caminhos padrão:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top