How can I use a .bat file to remove specific tokens from the PATH environment variable?

前端 未结 2 1422
北海茫月
北海茫月 2020-11-29 13:40

I am writing an uninstallation script, so I would like to \'undo\' modifications the installation made to the system. In achieving this goal, I would like to parse the

相关标签:
2条回答
  • 2020-11-29 14:23

    The batch code below removes 1 or more folder paths as defined at top of the script with PathToRemove1, PathToRemove2, ... from

    • user PATH of current user account stored in Windows registry under key
      HKEY_CURRENT_USER\Environment
    • system PATH stored in Windows registry under key
      HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment

    The update of system PATH requires administrator privileges which means the batch file must be executed as administrator if user account control (UAC) is not disabled for the user account executing the batch file.

    The batch code works only for Windows Vista and later versions of Windows because of command SETX is by default not available on Windows XP or even former versions of Windows.

    For availability of command SETX see SS64 article about SetX and Microsoft's SetX documentation.

    For the reg.exe output differences on Windows XP versus later Windows versions see Rob van der Woude's Reading NT's Registry with REG Query. The different output of reg.exe is taken into account by the batch code below.

    For an explanation why not using local PATH as currently defined on execution of the batch file read the questions, answers and comments of

    • How to set PATH environment variable in batch file only once on Windows?
    • Why are other folder paths also added to system PATH with SetX and not only the specified folder path?
    • What is the reason for nodemon working in cmd but not in a batch file?

    Commented batch code for folder path removal from user and system PATH:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "PathToRemove1=C:\Temp\Test"
    set "PathToRemove2=C:\Temp"
    
    rem Get directly from Windows registry the system PATH variable value.
    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 CheckSystemPath
        )
    )
    echo Error: System environment variable PATH not found with a value in Windows registry.
    echo/
    goto UserPath
    
    :CheckSystemPath
    setlocal EnableDelayedExpansion
    rem Does the system PATH not end with a semicolon, append one temporarily.
    if not "!SystemPath:~-1!" == ";" set "SystemPath=!SystemPath!;"
    rem System PATH should contain only backslashes and not slashes.
    set "SystemPath=!SystemPath:/=\!"
    
    rem Check case-insensitive for the folder paths to remove as defined at top
    rem of this batch script and remove them if indeed found in system PATH.
    set "PathModified=0"
    for /F "tokens=1* delims==" %%I in ('set PathToRemove') do (
        if not "!SystemPath:%%J;=!" == "!SystemPath!" (
            set "SystemPath=!SystemPath:%%J;=!"
            set "PathModified=1"
        )
    )
    
    rem Replace all two or more ; in series by just one ; in system path.
    :CleanSystem
    if not "!SystemPath:;;=;!" == "!SystemPath!" set "SystemPath=!SystemPath:;;=;!" & goto CleanSystem
    
    rem Remove the semicolon at end of system PATH if there is one.
    if "!SystemPath:~-1!" == ";" set "SystemPath=!SystemPath:~0,-1!"
    rem Remove a backslash at end of system PATH if there is one.
    if "!SystemPath:~-1!" == "\" set "SystemPath=!SystemPath:~0,-1!"
    
    rem Update system PATH using command SETX which requires administrator
    rem privileges if the system PATH needs to be modified at all. SETX is
    rem by default not installed on Windows XP and truncates string values
    rem longer than 1024 characters to 1024 characters. So use alternatively
    rem command REG to add system PATH if command SETX cannot be used or is
    rem not available at all.
    if "%PathModified%" == "1" (
        set "UseSetx=1"
        if not "!SystemPath:~1024,1!" == "" set "UseSetx="
        if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
        if defined UseSetx (
            %SystemRoot%\System32\setx.exe Path "!SystemPath!" /M >nul
        ) else (
            set "ValueType=REG_EXPAND_SZ"
            if "!SystemPath:%%=!" == "!SystemPath!" set "ValueType=REG_SZ"
            %SystemRoot%\System32\reg.exe ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" /f /v Path /t !ValueType! /d "!SystemPath!" >nul
        )
    )
    endlocal
    
    :UserPath
    rem Get directly from Windows registry the user PATH variable value.
    for /F "skip=2 tokens=1,2*" %%N in ('%SystemRoot%\System32\reg.exe query "HKCU\Environment" /v "Path" 2^>nul') do (
        if /I "%%N" == "Path" (
            set "UserPath=%%P"
            if defined UserPath goto CheckUserPath
            rem User PATH exists, but with no value, delete user PATH.
            goto DeleteUserPath
        )
    )
    rem This PATH variable does often not exist and therefore nothing to do here.
    goto PathUpdateDone
    
    :CheckUserPath
    setlocal EnableDelayedExpansion
    rem Does the user PATH not end with a semicolon, append one temporarily.
    if not "!UserPath:~-1!" == ";" set "UserPath=!UserPath!;"
    
    rem Check case-insensitive for the folder paths to remove as defined at top
    rem of this batch script and remove them if indeed found in user PATH.
    set "PathModified=0"
    for /F "tokens=1* delims==" %%I in ('set PathToRemove') do (
        if not "!UserPath:%%J;=!" == "!UserPath!" (
            set "UserPath=!UserPath:%%J;=!"
            set "PathModified=1"
            if not defined UserPath goto DeleteUserPath
        )
    )
    
    rem Replace all two or more ; in series by just one ; in user path.
    :CleanUser
    if not "!UserPath:;;=;!" == "!UserPath!" set "UserPath=!UserPath:;;=;!" & goto CleanUser
    
    rem Remove the semicolon at end of user PATH if there is one.
    if "!UserPath:~-1!" == ";" set "UserPath=!UserPath:~0,-1!"
    if not defined UserPath goto DeleteUserPath
    
    rem Update user PATH using command SETX which does not require administrator
    rem privileges if the user PATH needs to be modified at all. SETX is
    rem by default not installed on Windows XP and truncates string values
    rem longer than 1024 characters to 1024 characters. So use alternatively
    rem command REG to add user PATH if command SETX cannot be used or is
    rem not available at all.
    if "%PathModified%" == "1" (
        set "UseSetx=1"
        if not "!UserPath:~1024,1!" == "" set "UseSetx="
        if not exist %SystemRoot%\System32\setx.exe set "UseSetx="
        if defined UseSetx (
            %SystemRoot%\System32\setx.exe Path "!UserPath!" /M >nul
        ) else (
            set "ValueType=REG_EXPAND_SZ"
            if "!UserPath:%%=!" == "!UserPath!" set "ValueType=REG_SZ"
            %SystemRoot%\System32\reg.exe ADD "HKCU\Environment" /f /v Path /t !ValueType! /d "!UserPath!" >nul
        )
    )
    goto PathUpdateDone
    
    :DeleteUserPath
    rem Delete the user PATH as it contains only folder paths to remove.
    %SystemRoot%\System32\reg.exe delete "HKCU\Environment" /v "Path" /f >nul
    
    :PathUpdateDone
    rem Other code could be inserted here.
    endlocal
    endlocal
    

    The batch code above uses a simple case-insensitive string substitution and a case-sensitive string comparison to check if the current path to remove is present in user or system PATH. This works only if it is well known how the folder paths were added before and the user has not modified them in the meantime. For a safer method of checking if PATH contains a folder path see the answer on How to check if directory exists in %PATH%? written by dbenham.

    Attention: This batch code is not designed to handle the very rare use cases of system or user PATH contain a folder path with one or more semicolons in path string enclosed in double quotes to get the ; interpreted by Windows inside the double quoted folder path string as literal character instead of separator between the folder paths.

    For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

    • echo /?
    • endlocal /?
    • for /?
    • goto /?
    • if /?
    • reg /?
    • reg add /?
    • reg delete /?
    • reg query /?
    • rem /?
    • set /?
    • setlocal /?
    • setx /?

    See also Microsoft's article about Using command redirection operators for an explanation of >nul and 2>nul with redirection operator > being escaped with ^ to use the redirection on execution of reg.exe instead of interpreting 2>nul misplaced for command FOR which would result in an exit of batch processing by Windows command interpreter because of a syntax error.

    0 讨论(0)
  • 2020-11-29 14:35

    This command only outputs the first token, and no subsequent tokens are echoed.

    FOR /F "delims=;" %%A IN (%TEMP_PATH%) DO ECHO %%A 
    

    How can I loop through an unknown number of tokens and work with each one?

    Use the following batch file.

    SplitPath.cmd:

    @echo off
    setlocal
    for %%a in ("%path:;=";"%") do (
      echo %%~a
      )
    endlocal
    

    Example Output:

    F:\test>path
    PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\apps\WSCC\Sysinternals Suite;C:\apps\WSCC\NirSoft Utilities
    
    F:\test>splitpath
    C:\Windows\system32
    C:\Windows
    C:\Windows\System32\Wbem
    C:\Windows\System32\WindowsPowerShell\v1.0\
    C:\apps\WSCC\Sysinternals Suite
    C:\apps\WSCC\NirSoft Utilities
    

    Notes:

    • Modify the for loop as appropriate to implement the rest of your pseudocode.

    Further Reading

    • An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
    • for - Conditionally perform a command several times.
    • variable edit/replace - Edit and replace the characters assigned to a string variable.
    0 讨论(0)
提交回复
热议问题