I have a bat file that does a bunch of things and closes the cmd window which is fine when user double clicks the bat file from explorer. But if I run the bat file from a al
@dlchambers was close but set didn't work since cmdcmdline isn't a defined environment variable in some cases, but this version based on his works great for me:
echo %cmdcmdline% | findstr /i pushd >nul
if errorlevel 1 pause
Use exit /b 0
, not exit
The former will exit all the way if launched from Windows Explorer, but return to the console if launched from the command line.
It's not only possible, but your desired behavior is the normal behavior of batch file execution, unless you do something 'special':
So I think the question that needs to be answered is what are you doing in the batch file that causes the command window to close when you execute it by the command line?
Paste this at the beginning of your BAT or CMD script and maybe change what happens in the 'if' clause:
:: To leave command window open if script run from Windows explorer.
@setlocal
@set x=%cmdcmdline:"=%
@set x=%x: =%
@set y=%x:cmd/c=%
@if "%x%" neq "%y%" cmd /k %0 %* && exit || exit
@endlocal
What this does, is if the user either double-clicks or calls this script using "cmd /c" it will re-launch with "cmd /k" which will leave the session open after the command finishes. This allows the user to EXIT or maybe do something else.
The reason for doing it this way rather than the other ways explained in this answer is because I've found situations that still even with using the quotes or other symbols, the IF statement would barf with certain situations of the QUOTES and the /c and with spaces. So the logic first removes all QUOTES and then removes all spaces.. because SOMETIMES there is an extra space after removing the quotes.
set x=%cmdcmdline:"=% <-- removes all quotes
set x=%x: =% <-- removes all spaces
set y=%x:cmd/c=% <-- removes cmd/c from the string saving it to y
The point of the && exit || exit is so that if the ERRORLEVEL before exiting is 0 (success) it then stops running, but also if it is non 0 (some failure) it also stops running.
But you can replace this part:
cmd /k %0 %* && exit || exit
with something like
set CALLED_WITH_CMD_C=YES
and then make up your own differences in the rest of your script. You would have to then move or remove the endlocal.
The '@' symbol at front just prevents the echo, which you can have if you want to test. Do not use echo on or echo off as it changes the setting and affects all subsequent scripts that call yours.
%cmdcmdline%
gives the exact command line used to start the current Cmd.exe.
"%SystemRoot%\system32\cmd.exe"
.cmd /c ""{full_path_to_the_bat_file}" "
;%0
variable in your bat file, for in this case it is always the full path to the bat file, and always enclosed in double quotes.Personally, I would go for the %cmdcmdline%
approach (not %O
), but be aware that both start commands can be overridden in the registry…
after reading through the suggestions, this is what I went with:
set __cmdcmdline=%cmdcmdline%
set __cmdcmdline=%__cmdcmdline:"=%
set __cmdcmdline=%__cmdcmdline: =%
set __cmdcmdline=%__cmdcmdline:~0,5%
if "%__cmdcmdline%"=="cmd/c" set CMD_INITIATED_FROM_EXPLORER=1
set __cmdcmdline=
which conditionally sets the variable: CMD_INITIATED_FROM_EXPLORER
..and can subsequently be used as needed:
if defined CMD_INITIATED_FROM_EXPLORER (
echo.
pause
)
..but the issue regarding Powershell that @Ruben Bartelink mentions isn't solved:
running
./batch.cmd
from Powershell usescmd /c
under the hood