I'm trying to make a batch file that opens a certain exe and then, after (for example) 5 minutes, closes it then reopens it again. I have tried this:
#echo off
:loop
cd /d %~dp0
certain exe
timeout /t "time" (by minutes)
taskkill /f /im "certain exe"
goto loop
but it wouldn't close the exe nor open it, what can I do?
The problem is that cmd will wait for the current command to end before executing the next command, so timeout (and taskill) will not be executed until example.exe closes by itself.
To ensure that cmd doesn't wait example.exe, you'll need to use start /B, as in this example:
#echo off
:loop
start /B "example.exe"
ping -n seconds_of_delay+1 127.0.0.1>nul
taskkill /f /im "example.exe"
goto :loop
Replace seconds_of_delay+1 with the number of seconds you want the time period to last plus one.
/B is needed because, without it, start would execute example.exe in a new window (if you want that, simply use start).
I used ping as the way to create a time delay because it has been found to consume less processor time than sleep or timeout (you can find more details here).
Related
I need a little help here.
I need to create a .bat file to check if a process is running every 5 seconds. If the process is running then it simply resets and checks again in 5 seconds. If the process is not running, then it closes all other .bat files and restarts everything.
This is for a game server. So right now the whole process includes a few .bat files of which do different things. The initiate.bat starts the process by starting startserver.bat. startserver.bat then starts the game server, it's window opens and the server starts, it the starts the .bat file schedule.bat which sets a timer and is meant to restart the server once the timer has run out and then startserver.bat starts up anticrash.bat of which the code for it is below.
I have a feeling the code is not finding the server window or the process. I've double checked the process file name and have made sure that is correct. The title in the window for the server is simply the path to the .exe, but no matter what I've tried I can't get it to function correctly. It always ends up in a loop and not identifying the open or closed process and it simply defaults to "Server was not found!". If I swap the code it will simply loop "Server was found!" and proceed that way.
This is not the only example I've tried either. I've looked at literally every article I could find on how to check if a process or window was open. I've tried to add a title to the window and search for the title, I've tried other code configurations and if then statements and nothing works.
In the end I'd like the .bat to simply check if the server process is running or if the window is open, either way as I don't care how it identifies it, and if the server window is open and the server is running then simply recheck every 5 seconds. If it finds that the process or window was closed or ended, then it should close all other .bats and restart the process of initiating the server. It's mainly for when the server crashes I want it to restart if it does.
#echo off
goto check
:check
cls
echo Starting Anit Crash... Check every 5 Seconds...
SETLOCAL EnableExtensions
set EXE=program.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto FOUND
echo Server was not found!
echo Server may have crashed...
timeout /t 5
echo Shutting Down Other Processes First...
taskkill /f /im "schedule.bat"
echo Server Restarting...
start cmd /k call initiate.bat
echo Exiting Anti Crash...
timeout /t 3
goto FIN
:FOUND
echo Server Was Found...
echo Server Is Active... Rechecking In 5 Seconds...
timeout /t 5
goto check
:FIN
exit
It may solve your Problem
#echo off
:values
set EXE=safeincloud.exe
:check
cls
echo Starting Anti Crash... Check every 5 Seconds...
tasklist /fi "ImageName eq %EXE%" /fo csv 2>NUL | find /I "%EXE%">NUL
if "%ERRORLEVEL%"=="0" goto FOUND
echo Server was not found!
echo Server may be crashed...
timeout /t 5 >nul
echo Shutting Down Other Processes First...
taskkill /f /im "schedule.bat"
echo Server Restarting...
start "" "initiate.bat"
echo Exiting Anti Crash...
timeout /t 3 >nul
goto End
:FOUND
echo.
echo Server Was Found...
echo Server Is Active... Rechecking In 5 Seconds...
timeout /t 5 >nul
goto check
:End
exit
Source : How to check if a process is running via a batch script
I have searched and searched and this is the closest code I have found:
#echo off
:loop
C:\CryptoCurrency\nexus_cpuminer\start.bat
timeout /t 30 >null
taskkill /f /im nexus_cpuminer.exe >nul
goto loop
A few things: notice the start.bat. The .exe I need to launch has to start via the .bat file because the .bat file contains information the .exe needs.
Secondly, the .exe launches a CMD prompt window which shows me what's going on.
(keep this in mind because this is not your normal .exe, I WANT that CMD prompt window to close when it's KILLED)
I am aware I have it set for 30 seconds. I'm just testing right now. I'd like to set it for 4 hours before the kill command is called. Also, I'd like to set a "delay" of 30 seconds before the whole process starts over. I am running Windows 7 x 64.
You must change the name of the second Batch file to other name (i.e. starter.bat) and execute it via the start internal command in order to execute it in parallel:
#echo off
:loop
start "" cmd /C "C:\CryptoCurrency\nexus_cpuminer\starter.bat"
timeout /t 30 >null
taskkill /f /im nexus_cpuminer.exe >nul
goto loop
The last line in starter.bat file must be the execution of nexus_cpuminer.exe, so when it is killed via taskkill, the .bat file ends immediately.
Another simpler approach is to directly execute nexus_cpuminer.exe in this Batch file, via start "" cmd /C nexus_cpuminer.exe command, so this process be opened in its own cmd.exe window.
If you CALL start.bat, it will return to your 'calling' script.
If you give start.bat a TITLE, you can /FIlter your TASKKILL command to EQ that WINDOWTITLE
I'm installing a set of drivers in an unattended script. One of the drivers (Intel USB3 Drivers) kicks off the Windows Driver Finder application ("drvinst.exe") after it's finished. Then, when the nVidia Drivers try to run, they cancel out because that Wizard is still running in the background.
My current solution is this, but it is not very elegant:
:INSTALLLAPTOP79
.\ELAN\Touchpad\Setup.exe /s /a /s
.\Intel\Chipset\Setup.exe -s -norestart
.\Intel\Graphics\Setup.exe -s
.\Intel\MEI\Setup.exe -s
.\Intel\USB3\Setup.exe -s
.\Realtek\Audio\Setup.exe /s
.\Realtek\CardReader\Setup.exe /s
TIMEOUT 180
.\nVidia\Graphics\Setup.exe -n -s
GOTO :INSTALLLAPTOPWIFI
Basically if a system is slower than "normal" it will fail as the 180 seconds isn't enough. I could just increase this value but that is messy to me.
I'm basically looking for a way to do a "check" to see if the "drvinst.exe" is still running and if so wait for a set period - then do the check again.
Any ideas?
It's not guaranteed to work (it depends on how the installers launch the driver-finder) but:
start /wait command...
may do the trick. Be aware that if the command to be executed contains spaces, and needs to be wrapped in double-quotes, you'll need:
start /wait "" "c:\program files\something\..."
otherwise it will take the command as the title of the command-prompt.
#ECHO OFF
SETLOCAL
notepad
:waitloop
TASKLIST /fi "imagename eq notepad.exe" >NUL
IF ERRORLEVEL 1 timeout /t 1 /n&GOTO waitloop
GOTO :EOF
Here's a simple method waiting for notepad.exe to close. Adapt as you will...
#ECHO OFF
SETLOCAL
notepad
:waitloop
TASKLIST |find "notepad.exe" >NUL
IF ERRORLEVEL 1 timeout /t 1 /n&GOTO waitloop
GOTO :EOF
should work also
This works for me in Windows 10 (1903). Caveat: if you use it for a process that is running multiple times, it waits for all of them to finish before continuing.
Based on this answer by #Magoo which didn't work for me, but put me on the right track.
#ECHO OFF
notepad.exe
REM For the OP's original problem, put drvinst.exe instead of notepad.exe (here and below)
:waitloop
TASKLIST |find /I "notepad.exe" >NUL
IF ERRORLEVEL 1 GOTO endloop
REM echo Notepad running. Waiting 1 second...
timeout /t 1 /nobreak>NUL
goto waitloop
:endloop
echo Done!
i dont know if this is the best way to do it, but i know it works 100%
I use call in my scripts when i need it to wait.
:INSTALLLAPTOP79
Call \ELAN\Touchpad\Setup.exe /s /a /s
Call \Intel\Chipset\Setup.exe -s -norestart
Call \Intel\Graphics\Setup.exe -s
Call \Intel\MEI\Setup.exe -s
Call \Intel\USB3\Setup.exe -s
Call \Realtek\Audio\Setup.exe /s
Call \Realtek\CardReader\Setup.exe /s
Call \nVidia\Graphics\Setup.exe -n -s
GOTO :INSTALLLAPTOPWIFI
Call will make the script wait until the exe that's being ran is finished.
Not sure what purpose the . before the \ serves but you may need it if its there for a reason.
I am trying to install some windows standalone update files and to do this I need to use wusu.exe. Every now and again wusu.exe will hang. I have created a batch file called prereqs.bat and in this file I have calls to the wusu.exe. I need the code to kill wusu.exe if it hangs, and retry it again.
This is my code as it stands now:
:PreReqs32
taskkill /im prereqs32.bat /f
taskkill /im wusa.exe /f
when it loops back, it kills both the batch file and wusa.exe
start cmd /k c:\windows\temp\prereqs.bat
An outside process so that I can kill wusu.exe if things go awry.
timeout /t 240 /NOBREAK
this timeout is to wait until the install is complete which is sometimes not enough.
taskkill /im "[wusa.exe]" /fi "STATUS eq NOT RESPONDING"
if "%ERRORLEVEL%"=="1" goto PreReqs32
Is there a way for some sort of FOR loop, with logic to exit if the status is not "not responding"?
Also, as a bonus, is there a way to forgo the timeout and just "wait" for prereqs.bat to be complete before moving on, assuming that wusu.exe has not hung?
#call JBOSSbuildWar.bat > ..\logs\JBOSSbuildWar_out 2> ..\logs\JBOSSbuildWar_err
start cmd /c #call WeblogicbuildWar.bat > ..\logs\WeblogicbuildWar_out 2> ..\logs\WeblogicbuildWar_err
start cmd /c #call FEBAPortletWebWar.bat > ..\logs\FEBAPortletWebWar_out 2> ..\logs\FEBAPortletWebWar_err
start cmd /c #call buildStaticJBoss.bat > ..\logs\JBOSSFEBAStaticWar_out 2> ..\logs\JBOSSFEBAStaticWar_err
I have this set of batch files getting executed in order. I want to fork out this so that they execute in parallel. I have done that using start cmd /c. Now this will fork out new command prompt window for each of them. Assume there are some set of statements after this. I want to make sure they get executed only after all the forked batch files are finished. How to achieve this?
Lets say average time taken by each file is:
JBOSSbuildWar- 30 minutes
WeblogicbuildWar- 35 minutes
FEBAPortletWebWar- 30 minutes
buildStaticJBoss- 35 minutes
Since the main command prompt window has completed its task in 30 minutes, and the forked batch files needs another 5 minutes to complete, I want the main cmd to wait until the others are done. Kindly help.
there's multiple commands, you can choose what one to use,
Pause
Will pause cmd until the user presses any key.
Displays message, "Press any key to continue..."
I use a certain variation of this command called pause>nul.
What it does is pauses the .bat, but doesn't show a message, You just get a blank screen!
TIMEOUT
Multiple syntaxes, very useful command, use this one quite a bit.
Sample code: TIMEOUT 10
Can be bypassed by a key press
Pauses the execution of command by 10 seconds.
You can also structure it like this: TIMEOUT 10 /nobreak
Which does not allow the user to press a key to skip it, they must endure it!
Ping
Very nice one.
Syntax is like this: PING 1.1.1.1 -n 1 -w 60000 >NUL
Probably most complex of the three.
PING can be used to delay execution for a number of seconds.
Hope I helped!
-Logan
Easy way:
In your main batch,
del "%temp%\*.processfinished" >nul 2>nul
...
start ....whatever1.bat...
start ....whatever2.bat...
start ....whatever3.bat...
...
wait4all:
for /L %%a in (1,1,3) do if not exist "%temp%\%%a.processfinished" timeout /t 1 >nul &goto wait4all
:: continues here when all (3) processes have finished.
del "%temp%\*.processfinished" >nul 2>nul
Then in each of the (3) subsidiary .bat files, create a file "%temp%\x.processfinished" where x=1 for the first process, 2 for the second and so on.
When the sub-processes have started, the procedure waits until each has created its own ".processcompleted" file by checking whether any of the 3 is missing, if it it, timeout for 1 second and look again. Only if the 3 files are present will it continue.
In all probability, it would be best if the subsidiary processes could take an extra parameter (the name of this sub-process's "processfinished" file) rather than having a fixed number for each.
You could extend this, and use say the date and time to augment the filename so that this entire process could itself be run many times in parallel.
BTW - by starting the procedure with
#echo off
you can remove all of the leading #s (all that does is suppress the command-reporting for that one line.)
Also, start is happier as start "" ....., that is, with an empty window title in quotes as its first argument. This allows other arguments to be "quoted" as necessary - the very first "quoted" argument used is used as the "window title" for the process and is likely to be lost to the sub-process. Routinely assigning a dummy (empty if necessary) "window title" means you don't trip over this problem in the future.
You can add this timer function before each of the commands:
#call JBOSSbuildWar.bat > ..\logs\JBOSSbuildWar_out 2> ..\logs\JBOSSbuildWar_err
Timeout /t 60 /nobreak >nul
start cmd /c #call WeblogicbuildWar.bat > ..\logs\WeblogicbuildWar_out 2> ..\logs\WeblogicbuildWar_err
Timeout /t 60 /nobreak >nul
start cmd /c #call FEBAPortletWebWar.bat > ..\logs\FEBAPortletWebWar_out 2> ..\logs\FEBAPortletWebWar_err
Timeout /t 60 /nobreak >nul
start cmd /c #call buildStaticJBoss.bat > ..\logs\JBOSSFEBAStaticWar_out 2> ..\logs\JBOSSFEBAStaticWar_err
Ps: 60 stands for 1 minute, if you want 30 minutes, change it to 1800