Batch - how do I store the status of a program in a variable? - windows

I essentially want to write a script that can help a program restart itself if becomes 'not responding'. I then want to log this to a simple text file with the time so that I can check later how often it needed to restart, but how do I properly check the status and store that in a variable for the script to then decide whether to restart it or ignore it (as its otherwise either not running or running fine)?
I found that I can do something like.....
taskkill /im "myProgram.exe" /fi "STATUS eq NOT RESPONDING" /f >nul && start "" "C:\Program Files (x86)\myProgram\myProgram.exe"
which I got from Batch file to kill and restart not responding program
This is great and gets me part way there but when I append something to write to a log, I find it seems to write to the log anyway rather than only if the status is 'not responding'. It also doesn't offer me much flexibility to handle it in an if/else statement if I want to do something else with it.
This is what I tried with the appended bit....
taskkill /im "myProgram.exe" /fi "STATUS eq NOT RESPONDING" /f >nul && SET message=%time% %date% - myProgram is was not running so restarted it && ECHO %message% >> myProgram_restart_LOG.txt && START "" "C:\Program Files (x86)\myProgram\myProgram.exe"
(I guessed that && isn't conditional on the previous statement in the chain being successful but executes anyway regardless?)

&& is conditional. The problem is that you are setting a variable and trying to access it directly. so either do call echo to access the variabe:
taskkill /im "myProgram.exe" /fi "STATUS eq NOT RESPONDING" /f >nul && SET message=%time% %date% - myProgram is was not running so restarted it && call ECHO %message% >> myProgram_restart_LOG.txt & START "" "C:\Program Files (x86)\myProgram\myProgram.exe"
Alternatively, just echo the message directly to the log file.
taskkill /im "myProgram.exe" /fi "STATUS eq NOT RESPONDING" /f >nul && SET echo %time% %date% - myProgram is was not running so restarted it >> myProgram_restart_LOG.txt & START "" "C:\Program Files (x86)\myProgram\myProgram.exe"
But I am not sure why you want to chain inside of a batch file, so I would do:
taskkill /im "myProgram.exe" /fi "STATUS eq NOT RESPONDING" /f >nul
if errorlevel 0 (
echo %time% %date% - myProgram is was not running so restarted it>> myProgram_restart_LOG.txt
START "" "C:\Program Files (x86)\myProgram\myProgram.exe"
)

Related

.bat to check if a window or process is open or running and if it is do this if it is not do something else

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

How to verify tomcat is started successfully using batch script?

Have prepared a batch script to automate the build process. Was successfully able to figure out the success and failures of build using ant in batch script (%ERRORLEVEL%), accordingly displayed the message box with proper message.
Based on ant success have executed command to startup tomcat server, but how do i come to know in batch script whether it has been started or failed?
Your help is highly appreciated.!!
Thanks.
#echo off
call :is_running svchost.exe
echo %errorlevel%
call :is_running explorer.exe
echo %errorlevel%
call :is_running tomcat.exe
echo %errorlevel%
exit /b
:is_running
tasklist^
/fi "IMAGENAME eq %~1"^
/fi "STATUS eq running"^
/nh 2>nul | find "%~1" >nul || exit /b 1
exit /b 0
This calls a label named is_running and runs tasklist to find the ImageName running. If not running then errorlevel 1 is set. Added a few processes to test to display if it is working well.
Use the command tasklist /? for help.

Batch File calling Console Application - Leaves CMD window open

I am calling a C# Console Application via batch file, in order to send the application output into a text file, with the date/time etc.
The problem I have is that when the console application completes, it leaves the batch window open, because there is a PAUSE (the C# equivalent), so a key must be pressed for the window to close. This means I do not know when the job has finished.
Is there a way I can make the CMD window close when the application finished, without having to change the C# Application code?
#ECHO================================================================================
#ECHO The Application is currently running and may take some time. Please wait...
#ECHO================================================================================
#ECHO OFF
C:\Applications\Job\Job.exe > C:\Applications\Job\Job_Output\"Output_%date:/=-% %time::=-%.txt"
Try this (note the collated dot after echo):
echo.| C:\Applications\Job\Job.exe > C:\Applications\Job\Job_Output\"Output_%date:/=-% %time::=-%.txt"
I have tried with pause and it works well:
echo.| pause
echo. is not echo. It just prints a newline, just what you need to trigger the pause.
Not sure whether will it work if your console app already have a Console.ReadLine() or Console.ReadKey() method but instead of just calling the *.exe use the Start command which will run the executable in a separate window like
start "MyConsoleTask" C:\Applications\Job\Job.exe > C:\Applications\Job\Job_Output\"Output_%date:/=-% %time::=-%.txt"
If you have not access to the console app source code, you may try a workaround
#echo off
#echo================================================================================
#echo The Application is currently running and may take some time. Please wait...
#echo================================================================================
set "timeStamp=%date:/=-%_%time::=-%
set "timeStamp=%timeStamp:~0,-3%" & rem remove ,centiseconds.
set "logFile=C:\Applications\Job\Job_Output\Output_%timeStamp%.txt"
rem start the exe in the same cmd window
start /B "" """C:\Applications\Job\Job.exe" > "%logFile%"""
rem wait for process startup
ping 1.1.1.1 -n 1 -w 750 >NUL
rem wait for logFile to be closed. This may flag that job.exe has ended
:wait
ping 1.1.1.1 -n 1 -w 50 >NUL & rem this avoids processor load
2>nul (>>"%logFile%" call )||goto :wait
rem send a key to the console. This may be captured by the exe file
set "_vbs_file_=%TEMP%\sendConsole.vbs"
(
echo/ set oWS ^= CreateObject^("wScript.Shell"^)
echo/ wScript.Sleep 50
echo/ oWS.SendKeys "{ENTER}"
)>"%_vbs_file_%"
if exist "%TEMP%\sendConsole.vbs" (set "_spawn_=%TEMP%\sendConsole.vbs") else (set "_spawn_=sendConsole.vbs")
ping 1.1.1.1 -n 1 -w 50 >NUL
start /B /WAIT cmd /C "cls & "%_spawn_%" & del /F /Q "%_spawn_%" 2>NUL"
#echo================================================================================
#echo Process completed. I guess...
#echo================================================================================
exit/B
so,
start /B ...
starts the job.exe executable in the same cmd window.
:wait
ping 1.1.1.1 -n 1 -w 50 >NUL & rem this avoids processor load
2>nul (>>"%logFile%" call )||goto :wait
waits until logfile is closed, so it may indicate that the previous proccess has ended.
set "_vbs_file_=%TEMP%\sendConsole.vbs"
(
echo/ set oWS ^= CreateObject^("wScript.Shell"^)
echo/ wScript.Sleep 50
echo/ oWS.SendKeys "{ENTER}"
)>"%_vbs_file_%"
if exist "%TEMP%\sendConsole.vbs" (set "_spawn_=%TEMP%\sendConsole.vbs") else (set "_spawn_=sendConsole.vbs")
ping 1.1.1.1 -n 1 -w 50 >NUL
start /B /WAIT cmd /C "cls & "%_spawn_%" & del /F /Q "%_spawn_%" 2>NUL"
send the enter key to the console, so the process waiting a keystroke may capture it.
NOTE: the ping wait trick works fine only if the IP is unreachable.
NOTE: the call and/or goto trick is discussed here
we gotta simulate a key press here, therefore we should toy with the keyboard buffer.
I am no Batch expert and this is the answer I found searching how to press keys with a batch:
#if (#CodeSection == #Batch) #then
#echo off
set SendKeys=CScript //nologo //E:JScript "%~F0"
rem Open the command here
start "" /B Job.exe > JobOutput.txt
rem sends the keys composing the string "I PRESSED " and the enter key
%SendKeys% "I PRESSED {ENTER}"
goto :EOF
#end
// JScript section
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));
source:
Press Keyboard keys using a batch file
GnuWin32 openssl s_client conn to WebSphere MQ server not closing at EOF, hangs

Re-opening files in Batch

For definitely not malicious reasons, I need to have a batch file always open.
I have some base code:
:b
echo off
tasklist /fi "imagename eq cmd.exe" |find ":" > nul
if errorlevel 1 taskkill /f /im "game.bat"&start game.bat
goto b
And it works fine if want notepad.exe or blah.txt and etc.
Except for batch files, as the program itself is a batch file,
the system sees cmd.exe is already open.
It works except for batch files, as the system sees cmd.exe is already open.
Give your batch file a Title by adding the following command to game.bat:
title %~nx0
Check if game.bat is running by using tasklist with /v option:
:b
#echo off
tasklist /v | find "game.bat" > nul
rem errorlevel 1 means game.bat is not running, so start it
if errorlevel 1 start game.bat
rem timeout to avoid excessive processor load
timeout 60
goto b
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
tasklist - TaskList displays all running applications and services with their Process ID (PID) This can be run on either a local or a remote computer.
timeout - Delay execution for a few seconds or minutes, for use within a batch file.
title - Change the title displayed above the CMD window.

Command Line - Wait for a Process to Finish

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.

Resources