batch script to delete all icons from all users' desktops - batch-file

Currently looking for a way to delete all icons off of all user desktops. I have experimented until I made the following script that allowed me to delete all from a single user but without hard coding I won't be able to extend this to reach all users on a single PC.
#echo off
cd %%#
del C:\Users\%Userprofile%\Desktop\*.* /s /q
for /r %%# in (.) do rmdir %%# /s
cls
I am now looking to see if it is possible to extend this to multiple users without hard coding paths since I don't happen to know which user might be using the computer at the time.

Since you don't want to hard code path's, we can use the FOR to search for .ico files located in \Desktop for each user. The script bellow will search each users desktop, remove all .ico files, then prompt the user it has finished.
#ECHO OFF
#GOTO :search
:search
FOR /D %%G IN ("C:\Users\*") DO IF EXIST "%%~fG\desktop\*.ico" (
set correctDir=%%G\desktop
goto :foundFile
)
goto :finished
:foundFile
cd "%correctDir%"
del /S *.ico
goto :search
:finished
echo All Icons removed from users desktops!
pause
goto :eof
FOR /D iterates over all directories using the %%G variable. %%~fG expands to the full path to the directory in %%G.
IF EXIST checks if a file exists.
goto :eof exits the script

Extreme care must be taken when writing or working with scripts which are intended to delete files/folders. A single minor mistake can end up in a disaster.
For example this code: cd "MyFolder" & del /q *.* is extremely dangerous it delete all files from current directory with the assumption that previous cd command have changed the current directory to MyFolder, So in case of failure del command will delete all files from current directory which is not MyFolder. But this code is safe: cd "MyFolder" && del /q *.*. The del command will be executed only if the cd command have successfully changed the current directory to MyFolder.
Now back to your original problem of extending your code to wipe out 'Desktops' of all other users of the PC.
The first thing that should be considered is that a normal user typically does not have access to desktop folders of other users because of NTFS file system permissions which avoids non Administrators from accessing other users profile. So the resulting script will have to run with administrative privileges. Even running the script as Administrator does guarantee the success because each user can explicitly deny access to his/her user profile files/folders even to Administrators.
The other thing is while it is mostly the case that the desktop directory of each user is placed in a folder named Desktop located in the %USERPROFILE% directory e.g. C:\Users\John\Desktop but this is not always the case. In fact the desktop directory of each user can defined to be located anywhere and placed in a folder other than Desktop.
This is the case for other special folders other than Desktop.
So the correct approach is to first retrieve a list of user profiles from registry and then for each user profile query the location of user's desktop.
:: WipeDesktops.cmd
:: This script should be runned as Administrator to be able to access and delete the 'Desktop' contents of other users.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:: To turn TestMode off It is highly recommended that to invoke the script with "/TestMode:Off" switch rather than manually setting TestMode to 0
set "TestMode=1"
set "DeleteCommandConfirm=rd /s"
set "DeleteCommandUnsafe=rd /s /q"
for /F "tokens=1,2 delims=:" %%A in ("%~1") do if /i "%%A"=="/TestMode" (
if /i "%%B"=="Off" (set "TestMode=0") else set "TestMode=1"
)
set "DeleteCommand=%DeleteCommandConfirm%"
if %TestMode% NEQ 0 (
echo Running in Test Mode
set "DeleteCommand=echo %DeleteCommand%"
) else (
set "DeleteCommand=2>nul %DeleteCommand%"
)
set "SID_Prefix=S-1-5-21-"
set "ProfileList=HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList"
set "ShellFoldersBase=Software\Microsoft\Windows\CurrentVersion\Explorer"
set "ShellFolders=%ShellFoldersBase%\Shell Folders"
set "UserShellFolders=%ShellFoldersBase%\User Shell Folders"
for /F "delims=" %%K in ('reg query "%ProfileList%" /k /f "%SID_Prefix%"') do (
set "ProfileKey=%%~K"
set "ProfileKey=!ProfileKey:HKEY_LOCAL_MACHINE\=HKLM\!"
if "!ProfileKey!" NEQ "!ProfileKey:HKLM\=!" (
set "ProfilePath="
for /F "tokens=2*" %%A in ('reg query "!ProfileKey!" /v "ProfileImagePath" 2^>nul') do (
set "ProfilePath=%%~B"
)
if defined ProfilePath if exist "!ProfilePath!\" (
set "Desktop="
set "SID=!ProfileKey:%ProfileList%\=!"
for %%S in ("%UserShellFolders%", "%ShellFolders%") do (
if not defined Desktop (
for /F "tokens=2*" %%A in ('reg query "HKU\!SID!\%%~S" /v "Desktop" 2^>nul') do (
set "Desktop=%%~B"
)
if defined Desktop (
REM %USERPROFILE% value is different for each user so it can not be expanded
for %%A in ("!ProfilePath!") do set "Desktop=!Desktop:%%USERPROFILE%%=%%~A!"
if not exist "!Desktop!\" set "Desktop="
)
)
)
if not defined Desktop set "Desktop=!ProfilePath!\Desktop"
REM Skip network paths
if "!Desktop:~0,2!" NEQ "\\" if exist "!Desktop!\" (
cd /d "!Desktop!" 2>nul && (
echo Removing 'Desktop' contents in !Desktop! ...
REM Since there is an open handle to the 'Desktop' folder, The contents of the folder will be removed but the folder itself remains.
%DeleteCommand% "!Desktop!"
)
)
)
)
)
For safety reasons it has 2 modes of operation:
Test Mode (the default): In this mode it only shows the commands along with the path that it can delete but no actual deletion will be performed
Normal Mode (invoke with /TestMode:Off switch) which will list and actually deletes the detected user desktops.
How it works
It first retrieves a list user profiles from registry key: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList each of them located under a registry key with a name that is equal to the corresponding user SID beginning with S-1-5-21-
for each SID key it queries the value of ProfileImagePath to obtain the location of the user profile directory.
Then it queries the location of user's desktop from two registry locations in the listed order:
HKEY_USERS\<SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
HKEY_USERS\<SID>\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
and uses the value of ProfileImagePath to resolve the value of %USERPROFILE% variable for that user which is typically present in the special locations under the User Shell Folders key
Finally if the location of user's desktop can not be determined through registry then the default path of %USEPROFILE%\Desktop is assumed.
What is missing?
Shared user desktop is not covered, which is commonly located at %ALLUSERSPROFILE%\Desktop or %PUBLIC%\Desktop depending on windows version.
But the definite location can be obtained from these registry keys:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
So I'll leave it to you to do the rest and complete the missing part.

Related

Load user's registry, export data via batch file?

I need to be able to, if possible, via a batch file to export a user's mapped drive.
What I was thinking was have it load their ntuser.dat file, export hkey_current_user\Network key and save it to a certain location.
Is that possible?
Here's the script to call their username, this will be done locally on the computer:
:: Call the User Name :::::
:start
echo.
SET /P EndUserUN=EndUserUN:
echo.
REGEDIT.EXE /L:C:\Users\%EndUserUN%\NTUSER.DAT
Here's an example of a registry based script which should be Run as administrator and may perform the task for all of your users except for whoever you've logged in as:
#Echo Off
Set "EK=Network"
Set "RK=HKLM"
Set "SK=SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
Set "UI=S-1-5-21-"
Set "RV=ProfileImagePath"
Set "UH=NTUSER.DAT"
Set "TK=TmpHive"
Set "ER=HKU"
For /F "EOL=H Tokens=2*" %%A In (
'"Reg Query "%RK%\%SK%" /K /F "%UI%*" /S /V "%RV%" 2>Nul|FindStr /V "\.$""'
) Do (Reg Load "%ER%\%TK%" "%%~B\%UH%" 2>Nul
Reg Export "%ER%\%TK%\%EK%" "%~dp0%%~nxB.reg" /Y 2>Nul
Reg UnLoad "%ER%\%TK%" 2>Nul)
It is absolutely untested!
NoteDo not modify any line other than line 2, (which is currently Set to the SubKey path you are hoping to save as a .reg file).

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

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 PATH variable, and remove any values that the installation added to the PATH.
To do so, I developed the following pseudocode -
Save the contents of PATH to a temporary variable
Split the PATH into tokens, using the ; character as a delimiter, and loop through each token
(In Loop) Identify if the current token is one added by the installation
(In Loop) If the current token was not added by the installation, save it to be added to the updated PATH (in a temporary variable)
Save the updated PATH
I expected this to be relatively straightforward to implement.
The first step, storing the PATH is simple.
SET TEMP_PATH=%PATH%
However, when I try to loop through each token, it will not work as I expected.
FOR /F "delims=;" %%A IN (%TEMP_PATH%) DO ECHO %%A
This command only outputs the first token, and no subsequent tokens are echoed out.
So, I have two questions -
How can I loop through an unknown number of tokens and work with each one?
Is there another way to achieve the same goal which may be simpler?
Thank you.
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.
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.

Unable to delete folders currently working on using batch file

#echo off
rem setting folder variables
set "mymov=D:\Movies\My"
set "hermov=D:\Movies\Her"
set "themmov=D:\Movies\Them"
set folders=%mymov% %hermov% %themmov%
set ext=".mp4" ".mov" ".avi"
set test=0
for %%f in (%folders%) do (
echo "searching in %%f"
cd /D %%f
for %%i in (*.*) do (
for %%b in (%ext%) do (
if "%%~xi"==%%b (
set test=1
echo "match_found_not_deleting %%f")
)
)
if %test%==0 (
echo deleting %%f
rd /s /q %%f
)
)
I am trying to delete the folders stored in %%f but as my batch file is processing it I get an error that it is being used in some other process.
How can i fix it?
Please help.
Windows thinks that another application needs that folder and will not allow deletes until the other application is done using it. Try these items to find what else is accessing your folder.
check if you have another command window or windows explorer that is in (or under) that folder.
Check if you have a application open that is using a file in (or under) that folder.
Stop all the applications that are not absolutely needed.
if that doesn't work, reboot the computer, and only start the applications you need.

CMD deleting folder recursively (i.e. same folder name in multiple locations)

Due to a Dreamweaver setting mess-up, we've had thousands of "_notes" folders pop up in our websites dev & qa areas. There's too many to delete through Windows Explorer - everything just locks up - so I was hoping to run a batch script to sort it out for us once and for all. The problem is I'm not entirely sure that "rd /S" will do what I want.
My understanding is that rd /S will look recursively in the folder I tell it, so if I say:
rd /S r:/<siteName>/_notes/
then it will just look in the _notes folder and delete what's in there and then try to move further down that tree. What I need is a script that would take into account things like the following:
r:/<siteName>/_notes/
r:/<siteName/<someFolder>/_notes/
r:/<siteName/<someOtherFolder>/_notes/
r:/<siteName/<someFolder>/<someSubFolder>/_notes/
r:/<siteName/<someFolder>/<iThinkIveMadeMyPoint>/_notes/
Hope I made sense...
I found this in another thread, but it doesn't work with folders with a . in the name, so it's no use for site names...
#Echo OFF
REM Important that Delayed Expansion is Enabled
setlocal enabledelayedexpansion
REM This sets what folder the batch is looking for and the root in which it starts the search:
set /p foldername=Please enter the foldername you want to delete:
set /p root=Please enter the root directory (ex: C:\TestFolder)
REM Checks each directory in the given root
FOR /R %root% %%A IN (.) DO (
if '%%A'=='' goto end
REM Correctly parses info for executing the loop and RM functions
set dir="%%A"
set dir=!dir:.=!
set directory=%%A
set directory=!directory::=!
set directory=!directory:\=;!
REM Checks each directory
for /f "tokens=* delims=;" %%P in ("!directory!") do call :loop %%P)
REM After each directory is checked the batch will allow you to see folders deleted.
:end
pause
endlocal
exit
REM This loop checks each folder inside the directory for the specified folder name. This allows you to check multiple nested directories.
:loop
if '%1'=='' goto endloop
if '%1'=='%foldername%' (
rd /S /Q !dir!
echo !dir! was deleted.
)
SHIFT
goto :loop
:endloop
read HELP FOR, HELP SET and HELP IF
note that FOR /D /R will recursively walk the directory tree.
note also that %~na is the funny syntax to extract the name part of a full path.
so, putting this little pieces togethere, try this command on the command line
for /d /r %a in (*) do #if %~na==_notes #echo rd %a
after careful testing, remove the echo command.
This command has worked for me and I hope this could help. Switch to the common root folder, and type in CMD:
for /d /r . %d in (<folder name>) do #if exist "%d" rd /s/q "%d"
Change the to the name of folder you want to remove. Then all children folders with this name would be removed.

Why are other folder paths also added to system PATH with SetX and not only the specified folder path?

I have a batch file which I am calling from C++ using system("name.bat"). In that batch file I am trying to read the value of a registry key. Calling the batch file from C++ causes set KEY_NAME=HKEY_LOCAL_MACHINE\stuff to fail.
However, when I directly run the batch file (double clicking it), it runs fine. Not sure what I am doing wrong.
Batch file:
set KEY_NAME=HKEY_LOCAL_MACHINE\SOFTWARE\Ansoft\Designer\2014.0\Desktop
set VALUE_NAME=InstallationDirectory
REG QUERY %KEY_NAME% /v %VALUE_NAME%
C++ file:
int main(void)
{
system("CALL C:\\HFSS\\setup_vars.bat");
return 0;
}
UPDATE 1:
I found out that the key is actually in the 64-bit registry, and I was building my C++ solution as a 32-bit. Once I fixed that, it found the registry key fine.
Now I am having an issue adding that path to my PATH variable. Instead of creating a system variable, it is creating a user variable PATH and adding it there.
Running from command line works.
Code:
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
)
UPDATE 2:
I moved the placement of the option /M and it is now adding to right PATH variable.
However, when I am doing this, it is adding the PATH more than once (3 times) and then it is also adding a path to visual studio amd64 folder.
I'm mot sure why that is happening.
Windows creates a copy of the entire environment table of the process starting a new process for the new process. Therefore on start of your C++ application, your application gets the environment table including PATH from parent process, Windows Explorer or in your case Visual Studio. And this PATH is copied for cmd.exe on start of the batch file.
Taking the entire process tree into account from Windows desktop to the batch file, there have been many copies made for PATH and some processes perhaps appended something to their local copy of PATH like Visual Studio has done, or have even removed paths from PATH.
What you do now with SETX PATH "%PATH% is appending the local copy of PATH modified already by the parent processes in process tree completely to system PATH without checking for duplicate paths.
Much better would be to throw away all code using local copy of PATH and instead read the value of system PATH, check if the path you want to add is not already in system PATH and if this is not the case, append the path you want to add to system PATH using setx.
And this should be done without expanding the environment variables in system PATH like %SystemRoot%\System32 to C:\Windows\System32.
UPDATE
Here is the batch code required for your task tested on Windows 7 x64 and 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
The batch code above uses a simple case-insensitive string substitution and a case-sensitive string comparison to check if the folder path to append is present already in system PATH. This works only if it is well known how the folder path was added before and the user has not modified this folder path in PATH 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 Dave Benham.
Note 1: Command setx is by default not available on Windows XP.
Note 2: Command setx truncates values longer than 1024 characters to 1024 characters.
For that reason the batch file uses command reg to replace system PATH in Windows registry if either setx is not available or new path value is too long for setx. The disadvantage on using reg is that WM_SETTINGCHANGE message is not sent to all top-level windows informing Windows Explorer running as Windows desktop and other applications about this change of system environment variable. So the user must restart Windows which is best done always on changing something on persistent stored Windows system environment variables.
The batch script was tested with PATH containing currently a folder path with an exclamation mark and with a folder path being enclosed in double quotes which is necessary only if the folder path contains a semicolon.
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 /?
pause /?
reg /? and reg add /? and reg query /?
set /?
setlocal /?
setx /?

Resources