Abort external process if it takes too long to complete - batch-file

I am writing a batch script which processes many files at once using an external Python script. I'd like to implement a feature where, if the Python script hangs on any file for too long (e.g. the file is corrupted), the Python script will terminate and the batch script will move onto the next file. I have seen others on this site suggest using a timeout for terminating a program after a certain amount of time; however, that is far from ideal for this scenario, as that will add that many seconds to the running time of the script for each tile.
My question is: is there a way to limit the running time of an external process, without causing a delay if the process completes before the time is up?
Here is a bit of my code. TexIDfix.py at the end is the Python script which I need to prevent from hanging. Any help is much appreciated :)
:fixer
for /f %%f in ('dir /b "workspace\content\patch\data\fighter\%1\model\%3"') do (
set val=%%f
set val=!val:~1!
if /I !val!==01 set val=1
if /I !val!==02 set val=2
if /I !val!==03 set val=3
if /I !val!==04 set val=4
if /I !val!==05 set val=5
if /I !val!==06 set val=6
if /I !val!==07 set val=7
if /I !val!==08 set val=8
if /I !val!==09 set val=9
set /a "val=val*4"
if /I !val! GTR 255 (
set /a "mod/=255"
echo !mod!
set /a "val=val-(255*mod)"
echo !val!
)
TexIDfix.py "workspace\content\patch\data\fighter\%1\model\%3\%%f\%2.nud" "workspace\content\patch\data\fighter\%1\model\%3\%%f\model.nut" !val!
)
goto:eof

Related

Batch file to edit .ini file but do not delete blank space

I am new to StackOverflow. I want to run a batch file to find and replace a single string in an .ini file. I tried several solutions given on stackoverflow and other sites too.
A few of them are working - but delete my other lines having "space" or ";".
Here is the string that I want to find and change in my file RDConfigSettings.ini
CommunicationMode:1
I want it vice-versa:
if it is "CommunicationMode:1" then change it to "CommunicationMode:0"
if it is "CommunicationMode:0" then change it to "CommunicationMode:1"
Here is the whole content of my RDConfigSettings.ini file
;0 for Staging, 1 for Pre-Production, 2 for Production
RDEnviroment:2
;0 for disable, 1 for Enable
RDServiceLogs:0
;0 for disable, 1 for Enable
ClientValidation:0
;Validate Management Server Certificate -- 0 for Yes, 1 for No
ValidateCertificate:0
;Proxy Configuration -- 0 for Direct Internet Access, 1 for Access via Proxy
ProxyConfig:0
ProxyIP:[Proxy IP]
ProxyPort:[Proxy Port]
;0 for Https, 1 for Http
CommunicationMode:1
;Port Range Setting in below field
PortBegin:11100
PortEnd:11120
;ManagementServerURL
Registration:https://rdm.smartbioplus.com/rdm-device-app/registration
Keyrotation:https://rdm.smartbioplus.com/rdm-key-management-app/keyRotation
Telemetry:https://rdm.smartbioplus.com/rdm-telemetry-app/telemetry
Domain:rdm.smartbioplus.com
URL_Port:443
Could anyone help me? THis is my code:
#echo off
set "file=E:\CSC Softwares\MorphoRdServiceL0Soft\RDConfigSettings.ini"
:loop
findstr "^CommunicationMode:0$" "%file%" >nul || (
type "%file%"|repl "^CommunicationMode:1" "CommunicationMode:0" >"%file%.tmp"
move "%file%.tmp" "%file%" >nul
)
timeout 120 >nul
goto :loop
Moreover, it will be a great help if someone can add an Command with administrative rights that will stop a particular service "MORPHO_RD_Service" before replacing the string and then after replace the string, start the same service again.
You have code to switch from 1 to 0, but no code to switch from 0 to 1.
Below code alternates between 1 and 0 with each run of the loop.
I also changed to jrepl (more modern and powerful). It isn't necessary (though possible) to process piped data and redirect the result to another file. The /f switch gives the inputfile to process, the /o switch gives the outputfile. By giving it a single -, it uses the same filename as the input file (and overwrites it with the new(changed) data).
#echo off
set "file=t.txt"
:loop
findstr "^CommunicationMode:" "%file%" & REM this line for troubleshooting only
findstr "^CommunicationMode:0$" "%file%" >nul && (
call jrepl "CommunicationMode:0" "CommunicationMode:1" /f "%file%" /o -
) || (
call jrepl "CommunicationMode:1" "CommunicationMode:0" /f "%file%" /o -
)
timeout 1 >nul
goto :loop
Don't forget to adapt the data file name and the timeout to your needs.
Without the need for an external utility such as jrepl, which is great for some things, but not needed for such a task:
#echo off
setlocal enabledelayedexpansion
set "file=E:\CSC Softwares\MorphoRdServiceL0Soft\RDConfigSettings.ini"
for /f "tokens=1,*delims=]" %%i in ('type "%file%" ^| find /v /n "" ^& break^>"%file%"') do (
set "line=%%j"
if "!line!" == "CommunicationMode:1" (
set "line=!line:1=0!"
set "hold=!line!"
) else if "!line!" == "CommunicationMode:0" (
set "line=!line:0=1!"
set "hold=!line!"
)
echo(!line!>>"!file!"
)
echo Changed to !hold!
pause

.bat file that will start a process, get its PID, monitor its running condition

I am basically trying to write a script on WIN10 that will allow me to start a python script, monitor for it to complete before moving on the next step. This looks like it should work but it just loops at the 2s timer, even after I close the notepad windows. This is kind of a combination of 2 scripts I found on here so I may be way out to lunch on my methods.
#echo off
set PROCESSNAME=notepad.exe
::First save current pids with the wanted process name
setlocal EnableExtensions EnableDelayedExpansion
set "RETPIDS="
set "OLDPIDS=p"
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (set "OLDPIDS=!OLDPIDS!%%ap")
::Spawn new process(es)
start %PROCESSNAME%
::Check and find processes missing in the old pid list
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (
if "!OLDPIDS:p%%ap=zz!"=="%OLDPIDS%" (set "RETPIDS=/PID %%a !RETPIDS!")
)
:check
set stillalive=no
for /f "tokens=2" %%b in ('tasklist') do (
set pid=%%b
if !pid! == %RETPIDS% (
set stillalive=yes
)
)
if %stillalive% == yes (
cls
echo/Oh! He's still there, I'll wait.
timeout /t 2 /nobreak
goto check
) else (
echo/He's not there anymore, start the party!!
)
pause>nul
If there is a simpler way of doing this that's fine, if I can get this working with notepad, it should be easy to adapt to suit my needs.
Thanks in advance.
It's necro, I know, but I looked for something similar and just ended up here. This did a trick and fixed the script:
Replace
(set "RETPIDS=/PID %%a !RETPIDS!")
with
(set "RETPIDS=%%a!RETPIDS!")
The thing is that RETPIDS value looked like /PID 18465 and pid value was like 18465 and there also was a mess up with !!, %%, "%%" stuff and condition therefore strangely triggered every time although it obviously shouldn't.
Also seems that yours RETPIDS implies a possibility of several PIDs in one string like "5147 8463 6521" but it defenitely won't work with your single !pid! comparison in a loop.

How to stop a bat file from running if there is no response

I have a bat file that I created, it adds keys to the windows registry and then calls another bat file, QGIS.bat (this bat file starts an application called QGIS).
It works most of the time but every now and then, when it calls QGIS.bat nothing happens, the command window stays open but QGIS (started by the QGIS.bat file) will not start.
In the command window(cmd) all it says is call .\usbgis\apps\qgis\bin\qgis.bat
(Just a note QGIS is a portable application that runs from a USB memory stick, might that be part of the problem?)
So my question. Is there a way you can terminate a bat file if it douse not close in 3 min or if the other bat file douse not start?
Thanks,
This is what I'm talking about in my comment:
#echo off
setlocal enabledelayedexpansion
set sPath=C:\Program Files\Internet Explorer
set sprog=iexplore.exe
set inc=0
:loop
if exist "%sPath%\%sProg%" (echo %sProg%) else exit /b
set /a inc+=1
if "!inc!" equ "30" (Echo Exiting & exit /b)
for /f %%a in (
'tasklist /NH /FI "Imagename eq %sProg%"^|findstr /i "INFO:"') do (
if not errorlevel 1 (
ping -n 11 127.0.0.1>nul
goto :loop
)
)
Obviously change the path and file to match yours. I just needed something for testing here.

Editing and reading a .txt file with batch commands

I'm trying to create a batch file for an automated testing script.
Everytime the batch for the master script is started up, it should open an existing .txt-file in the same directory containing something like this:
10.200.6.111 inactive
10.200.6.112 inactive
10.200.6.113 inactive
10.200.6.114 inactive
etc...
It should then navigate to the line with it's own IP (which is specified in the batch) and replace the 'inactive' tag with 'active' (indicating that this system has now started testing). Ideally it would also append a timestamp, maybe with something along these lines:
for /f "tokens=1-5 delims=:" %%d in ("%time%") //and then add %%d-%%e at the end?
I've tried to do something similar before and also looked through existing topics but everything seems to be very specific to one situation and I lack the skills to adapt them myself. Ultimately I would need a different .bat to also read from this file and delay any action until all 'active' tabs are gone. But since as of now there is only one vm doing the testing, it would really be a weight off my shoulder if I could just get this to work. Thanks in advance for any help and I apologize if this is a duplicate, I really did try to find something I could use!
PS: I'm really terrible at 'getting' generic code sometimes, it's perfectly possible this has been clearly answered before and I'm just not capable of understanding the solution.
Edit: Just to clarify, it should look roughly like this:
10.200.6.111 inactive
10.200.6.112 inactive
10.200.6.113 active 14:20
10.200.6.114 inactive
etc...
Edit 2: Actually, after thinking about it some more, I've concluded that I can probably do it better by just using my scripts and keeping the batch files simple.
#echo off
setlocal enableextensions disabledelayedexpansion
:: define the log file
set "file=%~nx0.test.txt"
:: generate some lines in log file to test
if not exist "%file%" (
echo 10.200.6.111 inactive
echo 10.200.6.112 inactive
echo 10.200.6.113 inactive
echo 10.200.6.114 inactive
) > "%file%"
:: define the ip of the current node
set "ip=10.200.6.114"
:: change status in log file to active and shows sucess/failure of operation
call :changeStatus "%file%" "%ip%" "active %time:~0,5%"
if errorlevel 1 (
echo failed to change status
) else (
echo status changed
)
:: dump file to see changes
call :dumpFile "%file%"
:: change status in log file to inactive
call :changeStatus "%file%" "%ip%" "inactive"
:: dump file to see changes
call :dumpFile "%file%"
exit /B
:dumpFile file
echo(
echo(----------------------------------
type "%~1"
echo(----------------------------------
echo(
exit /b
:changeStatus file ip status
setlocal enableextensions
set "file=%~1"
set "ip=%~2"
set "status=%~3"
set "retries=0123456789"
set "exitCode=0"
:changeStatusRetry
(>"%file%.lock" (
set "reset=1"
for /f "usebackq tokens=1*" %%a in ("%file%") do (
if defined reset ( set "reset=" & >"%file%" break )
(if "%%a"=="%ip%" (
echo(%%a %status%
) else (
echo(%%a %%b
)) >> "%file%"
)
) && set "exitCode=0" || set "exitCode=1") >nul 2>nul
if "%exitCode%"=="1" (
ping -n 2 localhost >nul 2>nul
set "retries=%retries:~0,-1%"
if defined retries ( set "exitCode=0" & goto changeStatusRetry )
)
del /q "%file%.lock" >nul 2>nul
endlocal & exit /b %exitCode%
This uses a subroutine to handle the changes to log file. It also handles locking on the file from multiple processes. Log file access is locked while changing data and if at the time of changing the file it is locked, it retries up to 10 times to write changed data. On return from the subroutine, errorlevel indicates the result of the operation.

Removing lines from a txt file in batch

I need to check for certain processes (its a list of 20ish processes, so wont list them all), and record which ones are running. Then I need to kill them, run some other code, and finally reopen them... The code will only run successfully if all the processes have been ended.
I'd welcome any suggestions, or just someone to explain why my code doesn't work.
What I've been doing, is using tasklist to check for each process, and write the results to a file, then I'm trying to remove the lines of the file where the process is not running (i.e. I get an "INFO:..." message)
I know that I have done something similar before, where I've taken each line of a file one at a time (in a for loop), replaced a string of text within it, and sent the edited line to another file (which is probably not the most efficient way of doing it, but it worked).
For some reason, I can't replicate it now...
The code I've got (whch is failing) is
SETLOCAL ENABLEDELAYEDEXPANSION
cd\
for /f "tokens=* delims= " %%a in (somefile.txt) do (
set q=INFO: No tasks are running which match the specified criteria.
set r=%%a
set s=!r:%q%=!
echo %s% >>test.txt
)
If anyone knows of a better way to do what I need, I'm happy to change my plan, but it does need to be done through batch (CMD), or I'd be happy with some one fixing the above code at least.
Thanks
Try this code. Though I'm not sure if the output file matches the one you want. Make sure to surround the parameter with double quotes if it contains any space.
taskchk.cmd:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
if "%1" == "" (
echo Please specify criteria.
echo e.g.: taskchk myprocess.exe
goto :eof
)
cd\
type nul>test.txt
set found=0
for /f "tokens=*" %%a in ('tasklist /nh') do (
for /f "tokens=1" %%b in ("%%a") do (
if /i "%%b" == "%~1" (
set found=1
) else (
echo %%a>>test.txt
)
)
)
if %found% == 0 echo INFO: No tasks are running which match the specified criteria.>>test.txt

Resources