How to run a batch file in an another shell seamlessly - batch-file

I have this build file:
#echo off
call "%VS120COMNTOOLS%"\\vsvars32.bat
echo Deleting old exe...
del build_win32\dist\bin\OgreApp_d.exe
cd build_win32
echo Building As Debug
msbuild /detailedsummary /p:Configuration=Debug /p:Platform=x86 /t:build ALL_BUILD.vcxproj
echo Done building, Exiting.
cd dist\bin\
start OgreApp_d.exe
cd ../../../
And to run it I run from cmd build. The problem is that since I do not exit cmd between builds, the PATH grows and grows because of "%VS120COMNTOOLS%"\\vsvars32.bat until it refuses to run because path is too long. Is there a way I can start this in another shell but in the same place.
I could do
start cmd.exe /K "build.bat"
but it opens a new window and it is more complicated than just build

The advice of Bill_Stewart is very good and very easy to apply:
#echo off
setlocal
call "%VS120COMNTOOLS%"\\vsvars32.bat
echo Deleting old exe...
del build_win32\dist\bin\OgreApp_d.exe
cd build_win32
echo Building As Debug
msbuild /detailedsummary /p:Configuration=Debug /p:Platform=x86 /t:build ALL_BUILD.vcxproj
echo Done building, Exiting.
cd dist\bin\
start OgreApp_d.exe
cd ../../../
endlocal
A new local copy of the environment variables table is made with command setlocal. All changes on environment variables are done now on this local copy instead of the environment variables of always running command line interpreter process. The temporary local table of the environment variables is deleted by command endlocal. So value of PATH is not growing and growing on every execution of this batch file.
By the way: vsvars32.bat is obviously coded poorly as it does not check on current PATH if a folder path to add is not already included in PATH. My answer on Why are other folder paths also added to system PATH with SetX and not only the specified folder path? contains the few code lines to check PATH for a folder path to add before appending it to PATH.

Related

How to get the current path of my batch file? [duplicate]

I have a batch file that I intend to distribute to our customers to run a software task.
We distribute them as a folder or .zip with the files inside. Inside, there is the batch files and another folder with the files needed to run the batch.
Normally, when you make a batch, you type the path where the files are. But I won't know where the files are. The files will still be kept inside the master folder, but I need to have the batch find that folder to run the files.
So for example: If they have the master folder on the desktop and they run it, it would need to be something like "C:\Users\Username\Desktop" to run. You would have the batch CD to that location.
But what if they run it from documents? I don't know the username, so I have to somehow have the batch find this. Any code and/or instructions would be great.
There is no need to know where the files are, because when you launch a bat file the working directory is the directory where it was launched (the "master folder"), so if you have this structure:
.\mydocuments\folder\mybat.bat
.\mydocuments\folder\subfolder\file.txt
And the user starts the "mybat.bat", the working directory is ".\mydocuments\folder", so you only need to write the subfolder name in your script:
#Echo OFF
REM Do anything with ".\Subfolder\File1.txt"
PUSHD ".\Subfolder"
Type "File1.txt"
Pause&Exit
Anyway, the working directory is stored in the "%CD%" variable, and the directory where the bat was launched is stored on the argument 0. Then if you want to know the working directory on any computer you can do:
#Echo OFF
Echo Launch dir: "%~dp0"
Echo Current dir: "%CD%"
Pause&Exit
ElektroStudios answer is a bit misleading.
"when you launch a bat file the working dir is the dir where it was launched"
This is true if the user clicks on the batch file in the explorer.
However, if the script is called from another script using the CALL command, the current working directory does not change.
Thus, inside your script, it is better to use %~dp0subfolder\file1.txt
Please also note that %~dp0 will end with a backslash when the current script is not in the current working directory.
Thus, if you need the directory name without a trailing backslash, you could use something like
call :GET_THIS_DIR
echo I am here: %THIS_DIR%
goto :EOF
:GET_THIS_DIR
pushd %~dp0
set THIS_DIR=%CD%
popd
goto :EOF
You can also do
Pushd "%~dp0"
Which also takes running from a unc path into consideration.
Try in yourbatch
set "batchisin=%~dp0"
which should set the variable to your batch's location.

Batch file not working properly if I re run from a new command prompt

I have written a batch file for cleaning up the recovery files for one of my project work for testing. The script is explained below:
It will run an executable which takes a dll file as an argument and then run a process.
If the process is killed before doing some calculation, it creates recovery file.
Here my script will always load the dll after cleaning up the recovery files to avoid manually deleting the files by visiting a particular path.
To make generic, batch script will store the dll path and dll name in text files from where it will automatically pick the path.
Below is the batch script code:
#echo off
::Display the information first time if variables not set. Store them for future retrieval
set "currPath=%cd%"
if exist dllPath.txt (
set /p dllPath<=dllPath.txt
) else (
set /p dllPath="Provide game dll path (1st time only): "
::save the environment variables
echo %dllPath% > "dllPath.txt"
)
if exist dllName.txt (
set /p dllName<=dllName.txt
) else (
set /p dllName="Provide game dll name (1st time only): "
::save the environment variables
echo %dllName% > "dllName.txt"
)
::clean the data
cd /D %dllPath%
#echo %dllPath%
del *.bin
del *.recovery
%dllPath%\..\..\RunProcess.exe -dll %dllPath%\%dllName%
cd /D %currPath%
Issue with the script
First time on running the script from a command prompt, script is able to properly store the dll path and name properly in a text file.
If I run the script multiple times from the same command prompt, the process will run successfully.
But if I close the command prompt after running the script and try to run the script from newly opened command prompt, the script will throw error as
The syntax of the command is incorrect.
I tried to google about this and try to fix it, but couldn't. This may be a silly question to ask, but being novice in batch scripting I don't have any other option.
Place the = before the <.
set /p dllName=<dllName.txt

Batch script does not run in temporary folder after decompressing SFX WinRAR file

I have a program with a separate setup for 32 and 64 bits. My goal is to create a single executable that can run the appropriate setup. So I created a folder and placed the two setups inside, then wrote the following script:
#echo off
if %PROCESSOR_ARCHITECTURE%==AMD64 goto :x64
if %PROCESSOR_ARCHITEW6432%==AMD64 goto :x64
:x86
"%cd%"\setup.exe
exit
:x64
"%cd%"\setup-x64.exe
exit
Afterwards, I created the SFX file with this folder in WinRAR, pointing to the BAT file. But when I run it, a command line window pops up and shuts down instantly and nothing happens. I go to the temporary folder and double click the BAT file and the setup starts. The same happens in the original folder. What is happening and how can I fix it? Thanks!
%cd% reffers to the directory of the call of the batch-file.
For example a batch-file is in %USERPROFILE%\Desktop\Folder\bat.bat:
echo %cd%
pause
and you start it for example from the command-line like this:
C:\>%USERPROFILE%\Desktop\Folder\bat.bat
it should echo C:\ as that is where you called it from.
Two ways from the comments to solve the problem:
Push the directory of the batch-file using pushd "%~dp0" -> will result in a change of the variable value of %cd%
or
do not use "%cd%" but "%~dp0"
Both ways use the fact that the zeroth argument of a batch-file is its path.
You can prevent the command-line window from closing if you are debugging the file from the command-prompt itself if possible. With that you should have seen an error that state something like ...\setup.exe not found. After that nothing had to be done from the batch-file so it closed.

Environment changes made using "start" are not visible later in a batch file

I have a batch that is like this
#echo off
SET workspace="C:\yii2"
SET deploy_directory="C:\deployment"
SET source_file="C:\deployment\yii2"
SET destination_file="C:\deployment\deployment.zip"
cd "%source_file%"
start /wait update composer
start /wait xcopy "%workspace%" "%source_file%" /s /h /f
cd "%deploy_directory%"
start /wait zipjs.bat zipItem -source "%source_file%" -destination "%destination_file%" -keep yes -force no
pause
The bat file can anywhere be in the system.. So I write something like this.. Currently this is not working .. when it runs and change the directory the command prompt pops out and it does not process the next code.. Is there a silent way to change directory without interruption and will process the next command?
main goal is that to run composer update in the target path. Would appreciate also to explain what's happening here.
Pseudo:
1.) go to workspace path to update composer
2.) Copy workspace to a certain path with my zip bat
3.) change to that directory
4.) Run zipping bat
Edit: Added more steps
start starts a new command window. You just want to change the working directory of the command window that is going to run update. So don't use start for the cd bit:
cd "%source_file%"
start /wait update composer
One reason to use start is to run another batch file without terminating the current one. This works because the second batch file is run in a new command shell (and window). Usually, a better option is to use call, which runs the second batch file in the current command shell / window but doesn't terminate the current shell. In your case, since update is also a batch file, you can use call. So your script now looks like this:
cd "%source_file%"
call update composer

When is the CD environment variable updated?

The tipp to use the CD environment variable from batch scripts to get the current working directory is commonly posted. But CD won't get updated when calling another batch file. Then the cd command echoes the new path of the other batch file, but %CD% (or !CD!) is not updated. Example:
#echo off
cd %~dp0
echo in %0: CD=%CD%
pause
call X:\testcall.cmd
Save this as C:\testcall.cmd and X:\testcall.cmd, then run C:\testcall.cmd. You should see that the value of CD has not changed. This seems not to dependend on call; none of the following works:
start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
<NEW_DIR>\<OTHER_CMD_FILE>
cd %~dp0
pushd %~dp0
CD will keep it's old value, while cd (the command) shows the correct directory. Therefore I set CD at the begin of a script:
set CD=%~dp0
...while assuming cmd.exe sets CD only if this variable is yet unset. True?
%CD% is the current directory, while %~dp0 is the directory of the currently-running script (with trailing '\').
Also, don't set an env. var called CD, since it will override the default %CD% pseudo-var, and will be incredibly confusing - see OldNewThing - ERRORLEVEL is not %ERRORLEVEL%.
For example, when running c:\temp\a.cmd, which is:
#echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
cd %~dp0a
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%
output:
Currently running script: c:\temp\a.cmd
scriptDir=c:\temp\, CD=c:\temp
scriptDir=c:\temp\, CD=c:\temp\a
scriptDir=c:\temp\, CD=bogus value
Diagnosis
You have at some point set the CD variable explicitly. If you do this it will no longer automatically reflect the current working directory. To undo this, set it to empty:
set CD=
It will then begin working again.
Why is this? Well, the automatic CD variable was introduced as a feature. I assume they just didn't want to break pre-existing scripts which already used that varible name. So if you set it explicitly, CMD will assume you are doing so on purpose.
Discussion
Firstly, if the parent process has an explicitly set CD variable, it will be inherited by the child processes.
On the other hand, you shouldn't expect any of these to update the value of %CD% for the parent process:
start /D <NEW_DIR> <OTHER_CMD_FILE>
start cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
cmd /c <NEW_DIR>\<OTHER_CMD_FILE>
These all create new processes, the new process then changes its own working directory. You should not expect this to affect the parent process.
The final one, does not update the working directory at all, unless OTHER_CMD_FILE executes a CD command:
<NEW_DIR>\<OTHER_CMD_FILE>
Just because you executed a script in a different directory does not mean that the script's working directory will change. The script working directory does not have to be set to the location of the script.
Advice
Relying on the working directory being set to anything in particular is generally a bad idea.
You probably want something like this:
SET SCRIPT_DIR=%~dp0
Then use (for example) "%SCRIPT_DIR%\config.txt" to refer to a file in that directory.
Alternatively if you wish to rely on the current directory, use cd /d %~dp0
I build two batch files from your comment
test1.bat - located in C:\temp
#echo off
cd %~dp0
echo File %~f CD=%CD%
call X:\test2.bat
test2.bat - located in *X:*
#echo off
cd %~dp0
echo File %~f CD=%CD%
Starting test1 it from C:\temp, the output is
File C:\temp\test1.bat CD=C:\temp
File X:\test2.bat CD=C:\temp
The result is absolutly correct!
Starting a batch file (or any other program) with an absolute or relative path doesn't change the current directory.
The CD seems to fail, as CD can't change the drive the way you used it.
You need to add a switch CD /d %~dp0
You can set the %cd% variable to whatever you want, the real current directory for the C: drive is stored in the %=c:% variable, and you can't change this with the set command:
#echo off
echo Currently running script: %~dpnx0
cd %~dp0
echo scriptDir=%~dp0, CD=%CD%
set CD=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%
set =c:=bogus value
echo scriptDir=%~dp0, CD=%CD%, =c:=%=c:%
Output is:
Currently running script: C:\OldDir\a.bat
scriptDir=C:\OldDir\, CD=bogus value
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir
syntax error.
scriptDir=C:\OldDir\, CD=bogus value, =c:=C:\OldDir
The =C: variable for a child process is always set from the parent process. If you avoid the setlocal command in your script OR choose endlocal, you can change persistend the current directory for the current cmd session:
C:\OldDir>type script.bat
cd c:\newdir
C:\OldDir>script
C:\OldDir>cd c:\newdir
C:\NewDir>
.
C:\OldDir>type script.bat
setlocal
cd c:\newdir
C:\OldDir>script
C:\OldDir>setlocal
C:\OldDir>cd c:\newdir
C:\OldDir>
Using the script-directory %~dp0 can be a solution, but usually isn't. This works better:
cd >tmpfile
set /P CD= <tmpfile
del tmpfile
This solution is consistent with the CD variable. CD contains the current directory, not ending in a slash character if it is not in the root directory of the current drive. The path printed by cd behaves exactly so.
I'm using this for years and had no problems setting CD explicitly. Later I began using PWD (as in Bash). This variable is not reserved in MSDOS. So my question here was actually: "Can we get rid of these lines, or is this some MSDOS idiom?"
Some have written that setting CD explicitly is bad. Why? MSODS was never properly designed, and is not further developed. Anything you can do with it is legal. There is no bad MSDOS programming - just good and bad hacks. I know no other language where this perspective is legal to such an extent.

Resources