Superando o limite de 1024 caracteres com setx

74

Estou tentando definir variáveis ​​de ambiente usando o setxcomando, como a seguir

setx PATH "f: \ ferramentas comuns \ git \ bin; f: \ ferramentas comuns \ python \ app; f: \ ferramentas comuns \ python \ app \ scripts; f: \ ferramentas comuns \ ruby ​​\ bin; f: \ masm32 \ bin; F: \ Borland \ BCC55 \ Bin;% PATH% "

No entanto, recebo o seguinte erro se o valor tiver mais de 1024 caracteres:

AVISO: Os dados que estão sendo salvos são truncados para 1024 caracteres.

SUCESSO: o valor especificado foi salvo.

Mas alguns dos caminhos no final não são salvos em variável, acho que devido ao limite de caracteres, como o erro sugere.

Madhur Ahuja
fonte
Há uma lista de maneiras alternativas de editar o %PATH%
arquivo
11
Consulte o Rapid Environment Editor, que permite editar graficamente todas as variáveis ​​de ambiente (você também pode salvar um backup).
ja72
3
Alguém mais se incomoda com o sucesso dessa alegação quando claramente não faz o que foi solicitado? Não é preocupante que isso não falhe ao deixar o caminho exatamente como era?
Chad Schouggins
Isso ainda trunca no Windows 10?
cowlinator
11
Sim, ele funciona no Windows 10
Ivan

Respostas:

48

Sua melhor aposta é editar o registro diretamente.

Navegue HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environmente edite o Pathvalor (depois reinicie para ativar o novo valor).

Observe, porém, que embora você possa digitar um caminho muito longo (até o tamanho máximo da variável de ambiente; 2.048 ou 32.768 bytes, dependendo da fonte), nem todos os softwares poderão lê-lo e manipulá-lo corretamente se for muito longo.

Synetech
fonte
11
A reinicialização é realmente necessária aqui? Como setx faz isso? Setx não requer reinicialização.
Madhur Ahuja
11
Sim, é necessária uma reinicialização. setxedita o registro como indicado, depois transmite uma WM_SETTINGCHANGEmensagem. Isso informa a todas as janelas de nível superior que uma configuração do sistema foi alterada (neste caso, uma variável de ambiente). Sem isso, o Explorer e os programas que você abriu com ele não saberão sobre a alteração. Você pode transmitir a mensagem manualmente (eu escrevi um programa para fazer exatamente isso e um arquivo em lote para substituir SETXque faz com que uma edição do registro seja seguida pela transmissão), mas assim como setxa caixa de diálogo envvar Propriedades do sistema, ela tem efeitos colaterais faça a reinicialização preferível.
Synetech
2
Ah e editando um env.var. na verdade causa problemas se você não reiniciar, porque quaisquer variáveis ​​de ambiente que contenham outras variáveis ​​deixarão de ser expandidas. Por exemplo, eu apenas o transmito e agora esse é o meu caminho e recebo um erro porque o caminho agora está "quebrado" / vazio. Nenhum dos vars se expandirá corretamente novamente até eu reiniciar. Infelizmente isso é "normal". :-|
Synetech
3
Encontrei um pequeno script do PowerShell que transmitirá a mensagem WM_SETTINGCHANGE.
23812 Justin Dearing
10
Você pode usar o método de registro acima através do comando REG add e, em seguida, use SETX para definir outra variável para si mesmo (por exemplo: SETX / M USERNAME% USERNAME%). Isso fará com que a mensagem WM_SETTINGCHANGE seja definida e permita definir o caminho de um arquivo em lotes.
Art
30

se você estiver usando o Windows Vista ou superior, poderá fazer um symbolic linkpara a pasta. por exemplo:

mklink /d C:\pf "C:\Program Files"
mklink /d C:\pf86 "C:\Program Files (x86)"

criaria um link, assim c:\pfseria sua pasta de arquivos de programa. Raspei 300 caracteres do meu caminho usando esse truque.

(Eu sei que não está relacionado ao setx, mas é útil para pessoas que estão pesquisando superando o limite de 1024 caracteres)

Reza
fonte
18

Você pode usar um script do PowerShell semelhante ao seguinte:

$newPath = 'f:\common tools\git\bin;f:\common tools\python\app;f:\common tools\python\app\scripts;f:\common tools\ruby\bin;f:\masm32\bin;F:\Borland\BCC55\Bin'
$oldPath = [Environment]::GetEnvironmentVariable('path', 'machine');
[Environment]::SetEnvironmentVariable('path2', "$($newPath);$($oldPath)",'Machine');

A chamada da API Environment.SetEnvironmentVariable () será transmitida WM_SETTINGCHANGEpara que você não precise reinicializar.

Justin Dearing
fonte
Você também não precisa da seguinte linha: [Environment] :: SetEnvironmentVariable ('path', "$ newPath", 'Machine');
Fedor Steeman
11
Na terceira linha, não tenho certeza do benefício que os cifrões e parênteses extras trazem. Você não poderia apenas dizer [Environment]::SetEnvironmentVariable('path', "$newPath;$oldPath",'Machine')?
precisa saber é o seguinte
11
@twasbrillig Só tomo cuidado ao incluir uma variável em uma string. neste caso, é desnecessário.
Justin Dearing
3
Você pode chamar isso em um prompt de comando do administrador:@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -Command "[Environment]::SetEnvironmentVariable('path',\"C:\Program Files (x86)\GNU\GnuPG;$([Environment]::GetEnvironmentVariable('path','Machine'))\",'Machine');"
Mark C
7

Essa ferramenta de linha de comando SetEnv de código aberto é boa para editar o PATH e outras variáveis ​​de ambiente sem limitações. Ele usa um buffer dinâmico, sem limitações estáticas como 1024.

http://www.codeproject.com/Articles/12153/SetEnv

A escolha de um% como prefixo para anexar a uma variável poderia ter sido melhor, pois dificulta a sintaxe às vezes se usada com outras variáveis ​​locais em lote ...

Kharlos Dominguez
fonte
> A ferramenta SetEnv é boa para editar o PATH e outras variáveis ​​de ambiente sem limitações . Na verdade, eu havia trabalhado pessoalmente com a Darka nessa página para ajudar a tornar o SetEnv ainda melhor, para que ele possa dar suporte total às sub-variáveis ​​de expansão (a seção Expansão da variável dinâmica), o que realmente ajuda a reduzir o comprimento do caminho bruto.
Synetech
4

Uma ferramenta muito superior à setx para manipulação de caminhos é pathed.exe . Infelizmente, é limitado a editar o caminho.

Além de uma experiência de usuário superior à setx, você não tem um limite de 1024 caracteres. Ao contrário da manipulação direta do registro, este aplicativo usa a chamada da API Environment.SetEnvironmentVariable () que será transmitida WM_SETTINGCHANGE.

Justin Dearing
fonte
2
Há uma lista de outras ferramentas (incluindo pathed.exe) em superuser.com/questions/297947/is-there-a-convenient-way-to-edit-path-in-windows-7
Ehtesh Choudhury
2

Minha maneira favorita é alterar os nomes das pastas nas variáveis ​​PATH para usar os nomes 8.3. Essa resposta do StackOverflow possui um script impressionante (executado a partir de um arquivo .bat) que gera a versão "minificada" de toda a variável PATH, que você pode colar nas caixas de diálogo Editar variável. A única ressalva é que você precisará dividir as peças SYSTEM e USER. À medida que o script avança e descobre a versão reduzida para cada pasta, ele descarta e alerta você sobre quaisquer caminhos inválidos / inexistentes. Bom pequeno bônus de limpeza.

Andrew Steitz
fonte
Tenha cuidado se você tiver usado fsutil.exe behavior set disable8dot3 1.
Andrew Morton
@AndrewMorton bom ponto, mas isso não seria "tratado" pelo fato de o script não "gerar" o nome 8.3, apenas relata o nome 8.3 que o sistema de arquivos atribuiu? Portanto, se uma pasta não tivesse um nome 8.3, o script não proporia um substituto. No entanto, o uso de fsutil 8dot3name stripAPÓS o uso do script definitivamente causaria problemas nas pastas afetadas.
Andrew Steitz
Infelizmente, não tenho uma unidade ou sistema sobressalente para verificar. No entanto, tendo usado alguns fsutil 8dot3name stripanteriormente hoje e considerando que (a) verifica primeiro o registro e (b) o caminho é armazenado no registro, minha preocupação anterior pode ser injustificada, desde que o usuário não use a /fopção (force) .
Andrew Morton
2

Você pode colocar esta linha no seu BAT:

setx path "%%path%%;c:\drive\fr;c:\drive\installs\7z"

Veja o dobro %%.

(Referência: https://support.microsoft.com/en-us/kb/75634 )

Aminadav Glickshtein
fonte
Fazer a ligação agora é dividido
Ivan
11
AVISO! Isso possivelmente irá quebrar as coisas, ele gravará %path%;c:\...[snip]...\7zna pathvariável do usuário , descartando qualquer outra coisa que você tenha lá.
Eugene Petrov
A variável de ambiente PATH usada pelos programas é uma combinação da máquina e das variáveis ​​PATH locais. Além de destruir os dados atuais no caminho local, acho que isso não faz nada. Ter %path%a variável de ambiente do caminho local não deve ter efeito.
Annan
0

se não for necessário manter o PATH do sistema e o PATH do usuário separados:

::setx /m truncate variable length to 1024 REG ADD 
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PATH /t REG_SZ /f /d "%PATH%"
::empty local path, use system wide only, else it will enlarge with every setx /m
setx PATH ""
::setx is dummy but propagate system wide variables with it
setx /m A A
fantastory
fonte
11
Você pode explicar um pouco mais sobre o que está sugerindo aqui?
G-Man
É apenas um comando pronto para usar para solucionar o limite de setx 1024 caracteres. O exemplo é mostrado diretamente na variável PATH. Embora as respostas anteriores sejam úteis, elas não têm uma solução final.
fantastory
0

Acho que o melhor caminho é o próximo (com PowerShell). Dessa maneira, você evita o litmit de 1024 caracteres.

Você pode ver o código em: https://gist.github.com/drazul/b92f780689bd89a0d2a7

#------------ Add path to system variable -------------------------------------

$path2add = ';C:\path;'
$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

If (!$systemPath.contains($path2add)) {
    $systemPath += $path2add
    $systemPath = $systemPath -join ';'
    [Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');
    write-host "Added to path!"
    write-host $systemPath
}

#------------ Delete path from system variable --------------------------------

$path2delete = 'C:\path;'
$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

$systemPath = $systemPath.replace($path2delete, '')
$systemPath = $systemPath -join ';'

[Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');

write-host "Deleted from path!"
write-host $systemPath

#------------ Clean system variable -------------------------------------------

$systemPath = [Environment]::GetEnvironmentVariable('Path', 'machine');

while ($systemPath.contains(';;')) {
    $systemPath = $systemPath.replace(';;', ';')
}

[Environment]::SetEnvironmentVariable('Path', $systemPath, 'Machine');

write-host "Cleaned path!"
write-host $systemPath
Drazul
fonte