Преодоление ограничения в 1024 символа с помощью setx

74

Я пытаюсь установить переменные среды с помощью setxкоманды, например, следующим

setx PATH "f: \ common tools \ git \ bin; f: \ common tools \ python \ app; f: \ common tools \ python \ app \ scripts; f: \ common tools \ ruby ​​\ bin; f: \ masm32 \ бен; F: \ Borland \ BCC55 \ Bin;% PATH%»

Однако я получаю следующую ошибку, если значение превышает 1024 символа:

ВНИМАНИЕ: Сохраняемые данные усекаются до 1024 символов.

УСПЕХ: Указанное значение было сохранено.

Но некоторые пути в конце не сохраняются в переменной, я думаю, из-за ограничения символов, как предполагает ошибка.

Мадхур Ахаджа
источник
Список альтернативных способов редактирования можно %PATH%
найти
1
Загляните в Rapid Environment Editor, который позволяет графически редактировать все переменные окружения (вы также можете сохранить резервную копию).
ja72
3
Кто-то еще беспокоит это утверждение успеха, когда он явно не делает то, что было запрошено? Разве это не беспокоит, что это не терпит неудачу, оставляя путь точно, как это было?
Чед Шуггинс
Это все еще усекает на Windows 10?
cowlinator
1
Да, в Windows 10
Иван

Ответы:

48

Лучше всего редактировать реестр напрямую.

Перейдите к значению HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environmentи отредактируйте его Path(затем перезагрузите, чтобы активировать новое значение).

Однако обратите внимание, что, хотя вы можете ввести очень длинный путь (до максимальной длины переменной среды; 2048 или 32 768 байт в зависимости от источника), не все программное обеспечение сможет правильно читать и обрабатывать его, если он слишком длинный.

Synetech
источник
1
Здесь действительно требуется перезагрузка? Как setx это делает? Setx не требует перезагрузки.
Мадхур Ахуджа
11
Да, перезагрузка обязательна. setxредактирует реестр, как я указал, затем передает WM_SETTINGCHANGEсообщение. Это сообщает всем окнам верхнего уровня, что настройки системы изменились (в данном случае это переменная окружения). Без этого Explorer и программы, которые вы открыли с ним, не будут знать об изменениях. Вы можете транслировать сообщение самостоятельно (я написал программу для этого и пакетный файл для замены, SETXкоторый выполняет редактирование реестра, а затем трансляцию), но, как setxи в диалоговом окне «Свойства системы», у него есть побочные эффекты, которые сделать перезагрузку предпочтительнее.
Synetech
2
Ох, и редактирование env.var. на самом деле вызывает проблемы, если вы не перезагрузите компьютер, потому что любые переменные окружения, содержащие другие переменные, перестанут раскрываться. Например, я просто транслировал его, и теперь это мой путь, и я получаю сообщение об ошибке, потому что путь теперь «сломан» / пуст. Ни одна из варов не будет правильно расширяться, пока я не перезагрузлю К сожалению, это «нормально». :-|
Synetech
3
Я нашел небольшой скрипт PowerShell, который будет транслировать сообщение WM_SETTINGCHANGE.
Джастин Даринг
10
Вы можете использовать описанный выше метод реестра с помощью команды REG add, а затем использовать SETX, чтобы установить для себя некоторую другую переменную (например: SETX / M USERNAME% USERNAME%). Это приведет к установке сообщения WM_SETTINGCHANGE и даст вам возможность установить путь из пакетного файла.
Art
30

Если вы используете Windows Vista или выше, вы можете сделать symbolic linkв папку. например:

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

сделает ссылку, так c:\pfбудет ваша папка программных файлов. Используя этот трюк, я сбрил с пути 300 персонажей.

(Я знаю, что это не связано с setx, но это полезно для людей, которые ищут превышение на пределе 1024 символа)

Реза
источник
18

Вы можете использовать скрипт PowerShell, подобный следующему:

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

Environment.SetEnvironmentVariable () вызов API будет транслировать , WM_SETTINGCHANGEтак что вам не нужно перезагружать.

Джастин Даринг
источник
Вам также не нужна следующая строка: [Environment] :: SetEnvironmentVariable ('path', "$ newPath", 'Machine');
Федор Стиман
1
В 3-й строке я не уверен, какую пользу приносят дополнительные знаки доллара и круглые скобки. Не могли бы вы просто сказать [Environment]::SetEnvironmentVariable('path', "$newPath;$oldPath",'Machine')?
twasbrillig
1
@twasbrillig Я просто осторожен, когда включаю переменную в строку. в этом случае его нет необходимости.
Джастин Даринг
3
Вы можете вызвать это из командной строки администратора:@"%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');"
Марк C
7

Этот инструмент командной строки SetEnv с открытым исходным кодом хорош для редактирования PATH и других переменных среды без ограничений. Он использует динамический буфер, поэтому нет статических ограничений, как 1024.

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

Выбор% в качестве префикса для добавления к переменной мог бы быть лучше, хотя это иногда затрудняет синтаксис при использовании с другими пакетными локальными переменными ...

Харлос Домингес
источник
> Инструмент SetEnv хорош для редактирования PATH и других переменных среды без ограничений. Действительно. Фактически, я лично работал с Darka на этой странице, чтобы помочь сделать SetEnv еще лучше, чтобы он мог полностью поддерживать раскрывающиеся / под-переменные (раздел Динамическое расширение переменных), что фактически помогает сократить длину необработанного пути.
Synetech
4

Гораздо лучше, чем setx для манипулирования путями, - pathed.exe . К сожалению, это ограничено редактированием пути.

В дополнение к превосходному пользовательскому опыту, чем setx, у вас нет ограничения в 1024 символа. В отличие от прямых манипуляций с реестром, это приложение использует API-интерфейс Environment.SetEnvironmentVariable (), который будет транслироваться WM_SETTINGCHANGE.

Джастин Даринг
источник
2
Список других инструментов (включая pathed.exe) можно найти по адресу superuser.com/questions/297947/is-there-a-convenient-way-to-edit-path-in-windows-7
Ehtesh Choudhury,
2

Мой любимый способ - изменить имена папок в переменных PATH, чтобы использовать имена 8.3. Этот ответ StackOverflow содержит потрясающий скрипт (запускаемый из файла .bat), который сгенерирует «минимизированную» версию всей переменной PATH, которую затем можно вставить в диалоговое окно «Изменить переменную». Единственное предостережение в том, что вам нужно разделить части SYSTEM и USER. Когда скрипт проходит и выясняет минимизированную версию для каждой папки, он отбрасывает и предупреждает вас о любых неверных / несуществующих путях. Милый маленький бонус за уборку.

Эндрю Стейц
источник
Будьте осторожны, если вы использовали fsutil.exe behavior set disable8dot3 1.
Эндрю Мортон
@ AndrewMorton хорошая мысль, но разве это не будет «обработано» тем фактом, что скрипт не «генерирует» имя 8.3, он просто сообщает имя 8.3, которое присвоила файловая система? Таким образом, если папка не имеет имени 8.3, сценарий не предлагает замену. Однако использование fsutil 8dot3name stripПОСЛЕ использования скрипта определенно вызовет проблемы для затронутых папок.
Эндрю Стейтц
К сожалению, у меня нет запасного диска или системы, чтобы проверить это. Однако, использовав некоторые fsutil 8dot3name stripранее сегодня и учитывая, что (а) он сначала проверяет реестр и (б) путь хранится в реестре, моя более ранняя проблема может быть необоснованной, если пользователь не использует /fопцию (force) ,
Эндрю Мортон
2

Вы можете поместить эту строку в вашу BAT:

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

Смотри дабл %%.

(Ссылка: https://support.microsoft.com/en-us/kb/75634 )

Аминадав Гликштейн
источник
Ссылка не работает
Иван
1
ПРЕДУПРЕЖДЕНИЕ! Это, возможно, сломает вещи, оно запишет %path%;c:\...[snip]...\7zв пользовательскую pathпеременную, отбросив все, что у вас там было.
Евгений Петров
Переменная окружения PATH, используемая программами, является комбинацией машинных и локальных переменных PATH. В дополнение к уничтожению текущих данных в локальном пути, я не думаю, что это что-то делает. Наличие %path%в локальном пути переменной среды не должно иметь никакого эффекта.
Аннан
0

если не требуется разделять системный PATH и пользовательский PATH:

::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
источник
1
Можете ли вы объяснить немного больше о том, что вы предлагаете здесь?
G-Man говорит: «Восстановите Монику»
Это просто готовая команда для обхода установленного ограничения в 1024 символа. Пример показан непосредственно по переменной PATH. Хотя предыдущие ответы полезны, им не хватает окончательного решения.
фантастика
0

Я думаю, что лучший способ - следующий (с PowerShell). Таким образом, вы также избегаете мельчайших 1024 символов.

Вы можете увидеть код на: 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
источник