Ответ 1
Windows создает копию всей таблицы окружения процесса, начиная новый процесс для нового процесса. Поэтому при запуске приложения C++ ваше приложение получает таблицу среды, включающую PATH, из родительского процесса, проводника Windows или, в вашем случае, Visual Studio. И этот путь копируется для cmd.exe
при запуске пакетного файла.
Принимая во внимание все дерево процессов с рабочего стола Windows в пакетный файл, было сделано много копий для PATH, и некоторые процессы, возможно, добавили что-то в свою локальную копию PATH, например Visual Studio. сделал или даже удалил пути из PATH.
То, что вы делаете сейчас с SETX PATH "%PATH%
, добавляет локальную копию PATH, измененную уже родительскими процессами в дереве процессов, полностью в систему PATH, не проверяя дубликаты путей.
Гораздо лучше было бы выбросить весь код, используя локальную копию PATH, и вместо этого прочитать значение системного PATH, проверить, не существует ли путь, который вы хотите добавить, в системе PATH и, если это не так, добавьте путь, который вы хотите добавить в систему PATH, с помощью setx
.
И это должно быть сделано без расширения переменных среды в системе PATH, например %SystemRoot%\System32
, до C:\Windows\System32
.
UPDATE
Вот пакетный код, необходимый для вашей задачи, протестированной в Windows 7 x64 и Windows XP x86.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "KeyName=HKLM\SOFTWARE\Ansoft\Designer\2014.0\Desktop"
set "ValueName=InstallationDirectory"
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "%KeyName%" /v "%ValueName%" 2^>nul') do (
if /I "%%N" == "%ValueName%" (
set "PathToAdd=%%P"
if defined PathToAdd goto GetSystemPath
)
)
echo Error: Could not find non-empty value "%ValueName%" under key
echo %KeyName%
echo/
endlocal
pause
goto :EOF
:GetSystemPath
for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^>nul') do (
if /I "%%N" == "Path" (
set "SystemPath=%%P"
if defined SystemPath goto CheckPath
)
)
echo Error: System environment variable PATH not found with a non-empty value.
echo/
endlocal
pause
goto :EOF
:CheckPath
setlocal EnableDelayedExpansion
rem The folder path to add must contain \ (backslash) as directory
rem separator and not / (slash) and should not end with a backslash.
set "PathToAdd=%PathToAdd:/=\%"
if "%PathToAdd:~-1%" == "\" set "PathToAdd=%PathToAdd:~0,-1%"
set "Separator="
if not "!SystemPath:~-1!" == ";" set "Separator=;"
set "PathCheck=!SystemPath!%Separator%"
if "!PathCheck:%PathToAdd%;=!" == "!PathCheck!" (
set "PathToSet=!SystemPath!%Separator%!PathToAdd!"
set "UseSetx=1"
if not "!PathToSet:~1024,1!" == "" set "UseSetx="
if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
if defined UseSetx (
%SystemRoot%\System32\setx.exe Path "!PathToSet!" /M >nul
) else (
set "ValueType=REG_EXPAND_SZ"
if "!PathToSet:%%=!" == "!PathToSet!" set "ValueType=REG_SZ"
%SystemRoot%\System32\reg.exe ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /f /v Path /t !ValueType! /d "!PathToSet!" >nul
)
)
endlocal
endlocal
Приведенный выше пакетный код использует простую подстановку строк без учета регистра и сравнение строк с учетом регистра, чтобы проверить, присутствует ли путь к добавляемой папке в системе PATH. Это работает, только если хорошо известно, как путь к папке был добавлен ранее, и пользователь пока что не изменил этот путь к папке в PATH. Более безопасный способ проверки, содержит ли PATH путь к папке, приведен в ответе на вопрос Как проверить, существует ли каталог в% PATH%?, написанный Дейвом Бенхэмом.
Примечание 1: Команда setx
по умолчанию недоступна в Windows XP.
Примечание 2: Команда setx
усекает значения длиннее 1024 символов до 1024 символов.
По этой причине командный файл использует команду reg
для замены системного PATH в реестре Windows, если либо setx
недоступен, либо значение нового пути слишком длинное для setx
. Недостаток использования reg
заключается в том, что сообщение WM_SETTINGCHANGE не отправляется во все окна верхнего уровня, информирующее Проводник Windows, работающий в качестве рабочего стола Windows, и других приложений об этом изменении переменной среды системы. Таким образом, пользователь должен перезапустить Windows, что лучше всего делать всегда при изменении чего-либо в постоянных хранимых системных переменных Windows.
Пакетный скрипт был протестирован с PATH, который в настоящее время содержит путь к папке с восклицательным знаком и путь к папке, заключенный в двойные кавычки, что необходимо, только если путь к папке содержит точку с запятой.
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
иreg add /?
иreg query /?
set /?
setlocal /?
setx /?