将目录添加到路径环境变量



我的要求是在安装应用程序时将其中一个目录添加到windows中的路径环境变量中,并在使用批处理文件卸载时将其从环境变量中删除。

在stackoverflow的一个回答中,与此相关的建议如下,添加一个目录到路径环境变量中。

setx path C:Program Files (x86)MyApp

它正在添加到路径变量中,但当我尝试再添加一个时,它会覆盖我添加的现有值。如何避免这种情况?

如何从路径环境变量中删除我添加的目录路径?

您应该能够像这样使用它的现有值:

setx PATH %PATH%;C:Program Files (x86)MyApp

要删除它,你可能会做这样的事情:

setx PATH=%PATH:;C:Program Files (x86)MyApp=%

这将取代它被赋予的路径,而不需要删除它。

您需要检查path变量的用户部分是否为空,例如添加如下目录:

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_apppath=C:Program Files (x86)MyApp"
set "_keyBase=HKLMSYSTEMCurrentControlSetControlSession Manager"   machine
set "_keyBase=HKCU"                                                    user
set "_dataTyp="
set "_dataOld="
for /F "tokens=2,*" %%G in (' 
reg query "%_keyBase%Environment" -V path ^| findstr /I "<path>"
') do (
set "_dataTyp=%%G"
set "_dataOld=%%H"
)
if defined _dataOld (
set "_dataNew=%_apppath%;%_dataOld%"
) else (
set "_dataNew=%_dataOld%"
set "_dataTyp=REG_SZ"
)
rem debugging output: show script variables
set _
if /I "%~1" EQU "write" (
reg add "%_keyBase%Environment" -V path -T %_dataTyp% -d "%_dataNew%" -F
) else (
rem debugging output
ECHO reg add "%_keyBase%Environment" -V path -T %_dataTyp% -d "%_dataNew%" -F
) 
ENDLOCAL
goto :eof

请注意,我使用reg add而不是setx命令。另请参阅Rojo的回答,以获得详尽的解释。

输出

d:bat> D:batSO42140086.bat
_apppath=C:Program Files (x86)MyApp
_dataNew=C:Program Files (x86)MyApp;D:bare!;D:Remote
_dataOld=D:bare!;D:Remote
_dataTyp=REG_EXPAND_SZ
_keyBase=HKCU
reg add "HKCUEnvironment" -V path -T REG_EXPAND_SZ -d "C:Program Files (x86)MyApp;D:bare!;D:Remote" -F
d:bat> D:batSO42140086.bat write
_apppath=C:Program Files (x86)MyApp
_dataNew=C:Program Files (x86)MyApp;D:bare!;D:Remote
_dataOld=D:bare!;D:Remote
_dataTyp=REG_EXPAND_SZ
_keyBase=HKCU
The operation completed successfully.
d:bat> D:batSO42140086.bat
_apppath=C:Program Files (x86)MyApp
_dataNew=C:Program Files (x86)MyApp;C:Program Files (x86)MyApp;D:bare!;D:Remote
_dataOld=C:Program Files (x86)MyApp;D:bare!;D:Remote
_dataTyp=REG_EXPAND_SZ
_keyBase=HKCU
reg add "HKCUEnvironment" -V path -T REG_EXPAND_SZ -d "C:Program Files (x86)MyApp;C:Program Files (x86)MyApp;D:bare!;D:Remote" -F
d:bat>

上面的输出显示,只检查一个键是否为空是不够的,因为运行两次它也会添加两次相同的目录。

然而,检查path密钥(用户或机器范围)是否包含特定目录并不是一项简单的任务。例如,path中的某些条目包含尾随的反斜杠,而其他条目则不包含。此外,REG_EXPAND_SZpath注册表值中的一些条目可能与其他环境变量(例如%ProgramFiles%SomeApp而不是C:Program FilesSomeApp等)纠缠在一起。

以下复杂脚本TestPath.bat可以帮助分析Windowspath环境变量(请注意,由于启用了延迟扩展,如果路径包含感叹号!,它可能会显示不正确的值):

@ECHO OFF
set "HkcuEnv=HKCUEnvironment"
set "HklmEnv=HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironment"
SETLOCAL enableextensions enabledelayedexpansion
echo --- %date% %time% %~nx0 %*  
if /I "%~1" EQU "dir" (
set path
Call :printPath path "" dir %~2
echo/
echo tested using the following findstr regex: 
echo "%pathext:;=$ %$"
ENDLOCAL
goto :eof
)
set pathext
Call :duplicity pathext

Call :printPath path ""
Call :duplicity path
set "HKCU_type="
set "HKCU_path="
for /F "tokens=2*" %%G in (
'reg query HKCUEnvironment /v Path 2^>NUL ^|findstr /I "path"'
) do (
set "HKCU_type=%%G"
set "HKCU_path=%%H"
) 
Call :printPath HKCU_path %HKCU_type%
if /I "%HKCU_type%"=="REG_EXPAND_SZ" Call :printPath HKCU_path %HKCU_type% Expanded
set "HKLM_type="
set "HKLM_path="
set "qqqq=HKLMSYSTEMCurrentControlSetControlSession ManagerEnvironment"
for /F "tokens=2*" %%G in ('reg query "%qqqq%" /v Path^|findstr /I "path"'
) do (
set "HKLM_type=%%G" 
set "HKLM_path=%%H" 
) 
Call :printPath HKLM_path %HKLM_type%
if /I "%HKLM_type%"=="REG_EXPAND_SZ" Call :printPath HKLM_path %HKLM_type% Expanded
echo/
pause
REM echo/
REM set HK
echo/
echo/Usage: %~nx0
echo/       %~nx0 dir
echo/       %~nx0 dir all
ENDLOCAL
goto :eof
:printPath
echo/
echo %~0 %~1 %~2 %~3 %~4
if "!%~1!" NEQ "" (
set "ggg="!%~1:;=" "!""
rem set "ggg=!ggg:"="!"
for %%G in (!ggg!) do (
if /I "%~3" NEQ "expanded" (
if /I "%~3" EQU "dir" (
set "_partpath=%%~G"
if not "%~4"=="" ( 
echo/
echo "%%~G"
if /I "!_partpath:%SystemRoot%=!" EQU "%%~G" (
dir /B /A:-D "%%~G" | findstr /I "%pathext:;=$ %$"
echo errorlevel !errorlevel!
if errorlevel 1 pause
rem timeout /T 3 /NOBREAK >NUL
) else (
>NUL (dir /B /A:-D "%%~G" | findstr /I "%pathext:;=$ %$")
echo errorlevel !errorlevel!                system default
if errorlevel 1 pause
)
) else (
if NOT "%%~G"=="" (
for /F %%g in ('
2^>NUL dir /B /A:-D "%%~G" ^| findstr /I "%pathext:;=$ %$" ^| find "." /C
') do echo "%%~G" %%g file(s^)
) else (
echo "%%~G" ? file(s^)
)
)
) else (
echo "%%~G"
) 
) else (
call echo "%%~G"
)
)
)
goto :eof
:duplicity
echo/
echo %~0 %~1 %~2
set /A "ii=0"
set "ggg="!%~1:;=" "!""
set "ggg=!ggg:"="!"
for %%G in (!ggg!) do (
set /A "ii+=1"
set /A "jj=0"
for %%g in (!ggg!) do (
set /A "jj+=1"
if /I "%%~G"=="%%~g" if !ii! LSS !jj! echo !ii!, !jj!: %%~g 
)
)
goto :eof
REM TODO: unfinished procedure / incorrect output
:deflatePath
echo/
echo %~0 %~1 %~2
set "ggg="!%~1:;=" "!""
rem set "ggg=!ggg:"="!"
set "NewPath="
for %%G in (!ggg!) do (
set "item=%%~G"
set "meti="
call :deflateItem "ProgramFiles(x86)"
if defined meti (
rem echo # !item!
) else (
call :deflateItem "ProgramFiles"
if defined meti (
rem echo # !item!
) else (
call :deflateItem "SystemRoot"
if defined meti (
rem echo # !item!
) else (
rem echo = !item:%%=%%%%!
)
)
)
if defined NewPath (
set "NewPath=!NewPath!;!item!"
) else (
set "NewPath=!item!"
)
)
echo !NewPath!
rem reg delete HKCUEnvironment /v NewPath /f
rem setx NewPath "!NewPath!"
rem WARNING: The data being saved is truncated to 1024 characters.
rem reg query HKCUEnvironment /v NewPath|findstr /I "NewPath"
goto :eof
:deflateItem
set "meti=!%~1!"
if "!meti!"=="!item!" (
set "item=%%%~1%%"
) else (
set "meti=!item:%meti%=!"
if "!meti!" == "!item!" (
set "meti="
) else (
set "item=%%%~1%%!meti!"
)
)
goto :eof

最新更新