batch-file

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?


  1. 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)

  2. 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:

  1. %PATH% combina los valores en HKLM/System/CurrentControlSet/Control/Session Manager/Environment/Path con HKCU/Environment/Path . Cuando setx "dir;dir" , lo que está configurando es el valor de Path HKEY_CURRENT_USER . El valor de Path 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 usar setx /m para reemplazar el valor de la Path HKLM . Pero no lo haga, a menos que desee crear problemas graves con la instalación de su sistema operativo.

  2. Si desea probar si existe un directorio en %PATH% , puede cd o pushd 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 aplanados set "var=%CD%" para cada uno. Entonces if /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