batch file - modify - ¿Por qué también se agregan otras rutas de carpeta a la RUTA del sistema con SetX y no solo la ruta de carpeta especificada?
reg add bat (1)
Tengo un archivo por lotes al que llamo desde C ++ usando el
system("name.bat")
.
En ese archivo por lotes estoy tratando de leer el valor de una clave de registro.
Llamar al archivo por lotes desde C ++ hace que el
set KEY_NAME=HKEY_LOCAL_MACHINE/stuff
falle.
Sin embargo, cuando ejecuto directamente el archivo por lotes (haciendo doble clic en él), funciona bien. No estoy seguro de lo que estoy haciendo mal.
Archivo por lotes:
set KEY_NAME=HKEY_LOCAL_MACHINE/SOFTWARE/Ansoft/Designer/2014.0/Desktop
set VALUE_NAME=InstallationDirectory
REG QUERY %KEY_NAME% /v %VALUE_NAME%
Archivo C ++:
int main(void)
{
system("CALL C://HFSS//setup_vars.bat");
return 0;
}
ACTUALIZACIÓN 1:
Descubrí que la clave está realmente en el registro de 64 bits, y estaba creando mi solución C ++ como una de 32 bits. Una vez que solucioné eso, encontré que la clave de registro estaba bien.
Ahora tengo un problema al agregar esa ruta a mi variable PATH . En lugar de crear una variable del sistema, está creando una variable de usuario PATH y agregándola allí.
Ejecutar desde la línea de comandos funciona.
Código:
set KEY_NAME=HKLM/SOFTWARE/Ansoft/Designer/2014.0/Desktop/
set VALUE_NAME=InstallationDirectory
FOR /F "usebackq skip=1 tokens=1,2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME%`) DO (
set ValueName=%%A
set ValueType=%%B
set ValueValue=%%C
)
if defined ValueName (
@echo Value Value = %ValueValue%
) else (
@echo %KEY_NAME%/%VALUE_NAME% not found.
)
:: Set PATH Variable
set path_str=%PATH%
set addPath=%ValueValue%;
echo %addPath%
echo %ValueValue%
echo %PATH%| find /i "%addPath%">NUL
if NOT ERRORLEVEL 1 (
SETX PATH "%PATH%
) else (
SETX PATH "%PATH%;%addPath%;" /M
)
ACTUALIZACIÓN 2:
Moví la ubicación de la opción / M y ahora se agrega a la variable PATH derecha.
Sin embargo, cuando estoy haciendo esto, agrega la RUTA más de una vez (3 veces) y luego también agrega una ruta a la carpeta visual studio amd64.
Estoy seguro de por qué está sucediendo eso.
Windows crea una copia de la tabla de entorno completa del proceso que comienza un nuevo proceso para el nuevo proceso.
Por lo tanto, al iniciar su aplicación C ++, su aplicación obtiene la tabla de entorno, incluida la
RUTA
del proceso principal, el Explorador de Windows o, en su caso, Visual Studio.
Y esta
RUTA
se copia para
cmd.exe
al inicio del archivo por lotes.
Teniendo en cuenta todo el árbol de procesos desde el escritorio de Windows hasta el archivo por lotes, se han realizado muchas copias para PATH y algunos procesos quizás agregaron algo a su copia local de PATH como lo ha hecho Visual Studio, o incluso han eliminado rutas de PATH .
Lo que hace ahora con
SETX PATH "%PATH%
es agregar la copia local de
PATH
modificada por los procesos primarios en el árbol de procesos completamente a la
RUTA del
sistema sin verificar rutas duplicadas.
Mucho mejor sería tirar todo el código usando una copia local de
PATH
y, en su lugar, leer el valor de la
RUTA
del sistema, verificar si la ruta que desea agregar aún no está en la
RUTA del
sistema y, si este no es el caso, agregue la ruta que desea para agregar a la
RUTA del
sistema usando
setx
.
Y esto debe hacerse sin expandir las variables de entorno en la
RUTA del
sistema como
%SystemRoot%/System32
a
C:/Windows/System32
.
ACTUALIZAR
Aquí está el código de lote requerido para su tarea probada en Windows 7 x64 y 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
El código de lote anterior usa una simple sustitución de cadenas que no distingue entre mayúsculas y minúsculas y una comparación de cadenas que distingue entre mayúsculas y minúsculas para verificar si la ruta de la carpeta a agregar ya está presente en la RUTA del sistema. Esto funciona solo si se sabe bien cómo se agregó la ruta de la carpeta antes y el usuario no ha modificado esta ruta de la carpeta en PATH mientras tanto. Para un método más seguro de verificar si PATH contiene una ruta de carpeta, vea la respuesta en ¿Cómo verificar si el directorio existe en% PATH%? escrito por Dave Benham .
Nota 1: El
comando
setx
no está disponible por defecto en Windows XP.
Nota 2: El
comando
setx
trunca valores de más de 1024 caracteres a 1024 caracteres.
Por esa razón, el archivo por lotes utiliza el comando
reg
para reemplazar la
RUTA del sistema
en el registro de Windows si
setx
no está disponible o el nuevo valor de ruta es demasiado largo para
setx
.
La desventaja de usar
reg
es que el mensaje
WM_SETTINGCHANGE
no se envía a todas las ventanas de nivel superior informando al Explorador de Windows que se ejecuta como escritorio de Windows y otras aplicaciones sobre este cambio de la variable de entorno del sistema.
Por lo tanto, el usuario debe reiniciar Windows, lo que se hace mejor siempre al cambiar algo en las variables de entorno del sistema de Windows almacenadas persistentes.
El script por lotes se probó con PATH que contiene actualmente una ruta de carpeta con un signo de exclamación y una ruta de carpeta entre comillas dobles, que es necesaria solo si la ruta de carpeta contiene un punto y coma.
Para comprender los comandos utilizados y cómo funcionan, abra una ventana de símbolo del sistema, ejecute allí los siguientes comandos y lea con cuidado todas las páginas de ayuda que se muestran para cada comando.
-
echo /?
-
endlocal /?
-
for /?
-
goto /?
-
if /?
-
pause /?
-
reg /?
yreg add /?
yreg query /?
-
set /?
-
setlocal /?
-
setx /?