My click.bat file:
:main
#start /wait cmd.exe -/c ""C:\Users\MY_USER_NAME\Desktop\2.bat" "
goto :main
My 2.bat file:
#echo off
echo Hello World!
#pause
I am clicking Click.bat and they are both opening (no problem in here).
After that I am closing the Hello World! prompt (2.bat).
and prompt of the Click.bat, ask me ^CTerminate batch job (Y/N)?
I want to auto answer at here (as N).
(When the answer is N, 2.bat opening again like as I want).
I agree with Mofi that addressing the real issue is always better than to work around it, but sometimes this isn't possible or you need a quicker solution.
Instead of passively waiting, until the second process finishes, just actively watch it. If it isn't alive anymore, restart it. That way, it doesn't matter, how the second process finishes/exits/crashes:
test1.bat
#echo off
:main
if exist MyCommand.flag goto :eof
start test2.bat
:wait
timeout 1 >nul
tasklist /fi "Windowtitle eq MyCommand"|find "cmd.exe" >nul || #goto :main
goto :wait
test2.bat
#echo off
title MyCommand
echo Hello World!
#pause
break>MyCommand.flag
You don't have to start cmd /c, because start alone already starts a new cmd process. Give the process a unique title, so you can check, if it is still running.
|| works as "if previous command (find) fails then"
find is neccessary, because tasklist does not provide a helpful errorlevel.
Note: you also need a method to stop, when the second process finishes its task.
Test2.bat writes an empty file when finished. Obviously the file wouldn't be created, when the process crashes before (or is forcefully terminated).
test1.bat simply checks for the existence of the file before restarting the second process.
Related
I have a .bat file program like this
taskkill /f /im LearnBatV1.0.0.exe
timeout /t 1
start K:\POST\Govind\My Actual Work\LearnBat\LearnBatV1.0.0.exe
exit
LearnBatV1.0.0 is a simple application I created. I run the application and then I run the bat file. Then the bat file will execute the first two lines which will stop and close the application. But then when the third line tries to execut, it shows an error
K: \ POST \ Govind \ My Actual Work \ LearnBat \ LearnBatV1.0.0.exe could not be found. Make sure you typed the name correctly and try
again.
How is that it is correctly able to stop and close the application in the first line but not in the third line. The address is 100% correct. Then why is it giving an error. Kindly help me. Thank you.
I suggest using the following code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LoopCount=6"
set "ForceKill="
:EndProgramLoop
%SystemRoot%\System32\tasklist.exe /NH /FI "IMAGENAME eq LearnBatV1.0.0.exe" | %SystemRoot%\System32\find.exe /I "LearnBatV1.0.0.exe" >nul || goto StartProgram
set /A LoopCount-=1
if %LoopCount% == 0 (
echo ERROR: Failed to terminate LearnBatV1.0.0.exe!
echo/
pause
goto EndBatch
)
if %LoopCount% == 1 set "ForceKill=/F "
%SystemRoot%\System32\taskkill.exe /IM LearnBatV1.0.0.exe %ForceKill%>nul 2>nul
%SystemRoot%\System32\timeout.exe /T 1 /NOBREAK >nul
goto EndProgramLoop
:StartProgram
start "" "K:\POST\Govind\My Actual Work\LearnBat\LearnBatV1.0.0.exe"
:EndBatch
endlocal
The batch file checks first if LearnBatV1.0.0.exe is running at all. It starts the executable if that is not the case.
The first argument string enclosed in " is interpreted as title string for the console window even if the started executable is a Windows GUI window and so no console window is opened at all. For that reason "" is used to define an empty title string. The fully qualified file name of the executable is enclosed in " as required because of the space character, too. I recommend to use a meaningful title string if the executable is a Windows GUI application.
I hope, your program is coded to work with any directory as current directory as the current directory for LearnBatV1.0.0.exe is defined by the process starting cmd.exe to process this batch file and can be any directory for that reason.
But if LearnBatV1.0.0.exe is really running, there is first decremented by one an environment variable counting how often the loop to end the program is executed already with leaving the loop with an error message if it is not possible to get LearnBatV1.0.0.exe either gracefully self-terminated or finally brutally killed by the operating system.
There is tried four times to send the WM_CLOSE message via TASKKILL to all the running processes LearnBatV1.0.0.exe which should result in a graceful self-termination of the executable on not being very bad coded. There is used finally the option /F to force a brutal kill of the process by the operating system as last attempt.
There is made a delay of one second between each TASKKILL and TASKLIST execution to give the process the time it perhaps needs to gracefully terminate itself.
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 /?
find /?
goto /?
pause /?
set /?
setlocal /?
start /?
taskkill /?
tasklist /?
timeout /?
See also the Microsoft documentation about Using command redirection operators for an explanation of | and >nul and 2>nul and single line with multiple commands using Windows batch file for an explanation of conditional execution operator ||.
I am coding a virus using some BSOD code (I didn't make that part of it) and I want the file to, one started, give itself admin privilages, set the date and time to a certain point, and once the system date and time hit a certain point, self destruct. The problem I'm coming accross is that, the file is stuck on the process of keeping the BSOD on the screen, so it never gets to the self destruct code. Any help would be greatly appreciated. Thanks.
I've tried looping it and putting the code to when the loop reaches a certain point, move on. Didn't work.
#echo off
set loopcount=1
:loop
(
echo ^<html^>^<head^>^<title^>Microsoft Windows^</title^>
echo.
echo ^<hta:application id="oBVC"
echo applicationname="BSOD"
echo version="1.0"
echo maximizebutton="no"
echo minimizebutton="no"
echo sysmenu="no"
echo Caption="no"
echo windowstate="maximize"/^>
(This is the beggining of the code. It should loop once, then self destruct itself)
start "" /wait "bsod.hta"
del /f /q "bsod.hta" > nul
set /a loopcount=loopcount-1
if %loopcount%==0 goto exitloop
goto loop
:exitloop
del "%~f0" & exit
(This is the part where it should have made itself self destruct after the loop happened)
I expected it to loop once, the self destruct, ending all processes. It just stayed on the process of holding up the BSOD
I expected it to loop once, the self destruct, ending all processes.
It just stayed on the process of holding up the BSOD
Your start /wait command will most certainly wait until the hta file has been closed prior to continuing execution of the rest of the batch file. If you wish to have the hta display and continue execution, just remove the /wait
start "bsod.hta"
I need to know how can I check in batch file if the second batch file which is opened in other command window has stopped (waiting for argument or process not successful).
#echo off
:loop
start /wait rapidminer-batch.bat -f C:\Users\AHM-PC\Documents\ccc.rmp
echo cmd stopped
pause
goto loop
When called batch ends, it returns a value to errorlevel. It works for call, don't know if for start too.
if %errorlevel% gtr 0 (
echo failed
) else (
echo success)
or call exit /b <number of error> in your called batch, to return specific value. Check exit for more details.
The normal method to provide interbatch communication is a flag file
Either you create a flag file in the main routine and wait for the started routine to delete it or wait until the started batch creates a file, and delete it.
eg
echo.>myflag.txt
start anotherbatch.bat
:loop
timeout /t 1 >nul
if exist myflag.txt goto loop
Here, the batch will wait until myflag.txt is deleted, which you do in the second batch. All you need is for the two routines to agree on a filename to use.
I want to show a friend how big the impact of a fork bomb can be on performance, but without needing to restart the computer afterwards.
Assuming the following fork bomb:
%0|%0
Is there a way to add a kill switch to this which, with one button press, will stop all running copies of this file, stop any new from being created and hopefully save the machine? I'm not really familiar with the command prompt syntax, so I'm not sure.
Two ideas:
a) limit the depth your "bomb" is going to fork:
#echo off
set args=%*
if "%args%" EQU "" (set args=0) else set /a args=%args%+1
if %args% LSS 8 start /min thisfile.bat
(this will produce 2^9 -1 command windows, but only your main window is open.)
b) kill the cmd.exe process in the main batch file
#echo off
SET args=%*
:repeat
start /min thisfile.bat.bat some_arg
if "%args%" NEQ "" goto repeat
pause
taskkill /im cmd.exe
pressing any key in the initial batch file will instamntly kill all cmd windows currently open.
These solutions were tested with some restrictions, so if they work in a "hot" forkbomb, please let me know.
hope this helps.
EDIT:
c)implement a time switch in the original bat:
(still stops even if you can't get past pause)
#echo off
set args=%*
:repeat
start /min thisfile.bat some_arg
if "%args%" NEQ "" goto repeat
timeout /T 10
taskkill /im cmd.exe
or, using the smaller "bomb":
#echo off
set args=%*
if "%args%" NEQ "" (%0 some_arg|%0 some_arg) else start /min thisfile.bat some_arg
timeout /T 10
taskkill /im cmd.exe
If you're out to just show your friend fork bombs why not go for a silent but deadly approach? The fork bomb is in vbs, the cleanup is in batch.
Do note, the vbs fork bomb does nothing turning your pc off/on wont fix, it just floods your session proccess's.
The fork bomb:
Do until true = false
CreateObject("Wscript.Shell").Run Wscript.ScriptName
Loop
Source
Cleanup:
title=dontkillme
FOR /F "tokens=2 delims= " %%A IN ('TASKLIST /FI ^"WINDOWTITLE eq
dontkillme^" /NH') DO SET tid=%%A
echo %tid%
taskkill /F /IM cmd.exe /FI ^"PID ne %tid%^"
Source
If it runs in an accessible directory, you could try
IF EXIST kill.txt (exit /b) ELSE (%0|%0)
and make a file called kill.txt in the directory to stop the bomb.
Yes, I know you are probably going to complain saying it's a bad thing to do, but I want to do it anyway!
I am creating a batch program and at the end, I need it to hang and not accept user input. I know one method is just creating an infinite loop of:
:pause
pause > nul
goto pause
but I don't think that's a great choice. Although I need it to hang, I need to to be able to be closed via the red 'X' close button at the top of the window.
Any ideas?
This works for me. It redirects < NUL into self to prevent Ctrl+C from breaking, and uses start /b /wait to suppress the "Terminate batch job (Y/N)?" prompts.
#echo off
setlocal
>NUL (echo(%* | findstr "\<hang\>" && waitfor redX)
rem // *** PUT YOUR MAIN SCRIPT HERE ***
echo End of line.
rem // ******* END MAIN SCRIPT *********
call :hang
goto :EOF
:hang
start /b /wait "" "%~f0" hang ^<NUL
On the initial launch of the script, the echo(%* | findstr "\<hang\>" >NUL line looks for a script argument of "hang". If found, the script executes the waitfor command.
Normally, waitfor can be broken with Ctrl+C. But since the usual behavior of Ctrl+C is defeated by start /b and <NUL, the hanging effect is achieved unless a user does Ctrl+Break or sends the answering waitfor signal.
The red X still works, though.