batch file - ¿Cómo establecer la variable de entorno PATH en el archivo por lotes solo una vez en Windows?
batch-file (2)
Tengo un archivo por lotes que establece la ruta del usuario y se ejecuta como parte del paso de compilación IDE de Visual Studio.
@ECHO OFF
@ECHO %PATH%
set COMSPEC = "%VCINSTALLDIR%/vcvarsall.bat" amd64
setx PATH "../../lib/libsndfile;../../lib/simulink"
@ECHO %PATH%
Cuando construyo el proyecto, cierro VS y lo vuelvo a abrir, y reconstruyo, veo la ruta adjunta como parte de la variable
PATH
.
Sin embargo, veo que en la configuración de Windows de la variable de entorno, la variable
PATH
se crea en las variables de entorno del usuario como
../../lib/libsndfile;../../lib/simulink
Pregunta 1:
¿Por qué esta ruta también aparece como ruta adjunta como parte de la variable de entorno del sistema?
Al ejecutar
echo %PATH%
través de la consola de Visual Studio (cuando ejecuto el proyecto por segunda vez) imprime la ruta de la variable del sistema y la nueva ruta que creé adjunta.
Pregunta 2:
Quiero modificar mi archivo por lotes para que solo se establezca una vez la variable de entorno
PATH
en la configuración del usuario durante la primera ejecución de la compilación de Visual Studio.
Si la variable de usuario
PATH
ya existe en ejecuciones posteriores, no debe ejecutar el comando
set
nuevamente para evitar agregar una nueva ruta una y otra vez en la variable del sistema.
¿Alguna idea de cómo lograr esto?
-
Eso es lo que hace Setx. Ver
Setx /?
donde te dice esto. Lo agrega al entorno del usuario de forma permanente (a menos que se use / m). Sin embargo,% PATH% se crea a partir de la RUTA del sistema y del entorno del usuario (y también autoexec.bat en ventanas de 32 bits y, si se inicia a través de ShellExecute, también la clave de registro de rutas de aplicaciones) -
No te preocupes por eso. Setx no agrega rutas a% PATH% si ya existen en% PATH%.
¿Por qué está redefiniendo la variable del sistema% COMSPEC%?
editar: después de algunas pruebas, parece que mi respuesta original no es totalmente aplicable a las preguntas de OP. Para responder OP más directamente:
-
%PATH%
combina los valores enHKLM/System/CurrentControlSet/Control/Session Manager/Environment/Path
conHKCU/Environment/Path
. Cuandosetx "dir;dir"
, lo que está configurando es el valor dePath
HKEY_CURRENT_USER
. El valor dePath
HKEY_LOCAL_MACHINE
toda la máquina permanece intacto. Es por eso que ve sus valores como adjuntos, en lugar de como reemplazos. Tendría que usarsetx /m
para reemplazar el valor de laPath
HKLM
. Pero no lo haga, a menos que desee crear problemas graves con la instalación de su sistema operativo. -
Si desea probar si existe un directorio en
%PATH%
, puedecd
opushd
tanto al directorio que desea verificar como a cada directorio dentro de%PATH%
para unificar cada uno, asegurándose de que todas las rutas relativas, variables de entorno, etc. son aplanadosset "var=%CD%"
para cada uno. Entoncesif /I "!dir1!"=="!dir2!"
el directorio ya existe en algún lugar en%PATH%
. Hay un ejemplo de esto en mi respuesta original a continuación.
La razón por la que mi respuesta original no es completamente aplicable es porque
setx
sí no es tan destructivo como alguna vez pensé.
El peligro es que, a menudo, cuando los usuarios desean agregar un directorio a su ruta, establecerán
setx /m PATH "%PATH%;new dir"
;
Y eso
es
destructivo.
Debido a que
%PATH%
se expande antes de que
setx
escriba el valor, todos los directorios en PATH se expanden prematuramente.
El siguiente método sería más seguro:
set "env=HKLM/System/CurrentControlSet/Control/Session Manager/Environment"
for /f "tokens=2*" %%I in (
''reg query "%env%" /v Path ^| findstr /i "/<Path/>"''
) do setx /m PATH "%%J;new directory"
Pero eso no fue realmente lo que OP preguntó, y me disculpo por la respuesta instintiva.
respuesta original:
setx
es destructivo y no debe usarse de esta manera.
Cuando
setx PATH
, está convirtiendo el tipo de datos del valor del registro de REG_EXPAND_SZ a REG_SZ.
Tan pronto como haga esto, todas las variables de entorno dinámico almacenadas en su% PATH% se convierten en rutas planas y absolutas.
Use el comando de
path
para agregar directorios a su
%PATH%
temporalmente, y
reg add
para hacerlo permanentemente.
(Como nota al margen, también hay
dpath
, que agrega temporalmente un directorio a su ruta, pero solo puede ser usado por el comando
type
. Desplácese 2/3 hacia abajo en
esta página
para obtener más información sobre
dpath
).
Aquí hay un script de utilidad que escribí para agregar directorios a mi
%PATH%
de una manera menos destructiva.
También evitará agregar el mismo directorio a
%PATH%
más de una vez, independientemente de cómo esté formateado (por ejemplo, barra diagonal inversa, rutas relativas, variables de entorno o cualquier otra permutación).
@echo off
setlocal enabledelayedexpansion
if not exist "%~1" goto usage
for %%I in ("%~1") do pushd "%%~I" 2>NUL && (set "new=!CD!" && popd) || goto usage
for %%I in ("%PATH:;=";"%") do pushd "%%~I" 2>NUL && (
rem // delaying expansion of !new! prevents parentheses from breaking things
if /i "!new!"=="!CD!" (
echo !new! already exists in %%PATH%%
goto :EOF
)
popd
)
call :append_path "%new%"
goto :EOF
:usage
echo Usage: %~nx0 "dir"
goto :EOF
:append_path <val>
set "env=HKLM/System/CurrentControlSet/Control/Session Manager/Environment"
for /f "tokens=2*" %%I in (''reg query "%env%" /v Path ^| findstr /i "/<Path/>"'') do (
rem // make addition persistent through reboots
reg add "%env%" /f /v Path /t REG_EXPAND_SZ /d "%%J;%~1"
rem // apply change to the current process
for %%a in ("%%J;%~1") do path %%~a
)
rem // use setx to set a temporary throwaway value to trigger a WM_SETTINGCHANGE
rem // applies change to new console windows without requiring a reboot
(setx /m foo bar & reg delete "%env%" /f /v foo) >NUL 2>NUL
color 4E
echo Warning: %%PATH%% has changed. Reopen the console to inherit the changes.
goto :EOF