2

I would like a command in a batch file to only execute if it has not been ran for the last 15 minutes. To achieve this I can create a "last_run" file to log the time last ran.

Where I am stuck is comparing the time last modified to the current time and taking action if the time last modified.

Here is my current code:

@echo off
set filename=last_run.txt
if not exist %filename% (
   rem NOT EXISTS, CREATE FILE THEN PRINT THE LIST
   echo.>"%filename%"
   GOTO PrintList
) else (
   rem FILE EXISTS, GET TIME LAST MODIFIED
   FOR %%? IN (%filename%) DO (set filetime=%%~t?)
   echo %filetime%
   rem IF TIME LAST MODIFIED > 15 MINS PRINT THE LIST
   if timediff??(%filetime%, current) > 15 mins {
      GOTO PrintList
   } else {
      GOTO End
   }
)

:PrintList
rem PRINT THE LIST
echo now print the list
rem WRITE TO THE FILE TO UPDATE TIME LAST MODIFIED
echo.>"%filename%"
GOTO End

:End
  • This is a script I wrote previously for this purpose. With a few modifications, minutes could be included in the comparisons. Minor adjustments will allow for operation of the program on your logfile without input being required `https://pastebin.com/hNCgcLLa` The script demonstrates conversions and substring modifications that can be used to create comparable date time information between current time and file time – T3RR0R Feb 18 '20 at 12:25
  • with regards to comparison operators in your example script, `GTR GEQ EQU LEQ LSS` and `If "%Var%"=="value"` or `If Not "%Var%"=="value"` are valid, `<` and `>` are not - in batch they are redirection characters. – T3RR0R Feb 18 '20 at 12:28

3 Answers3

1

Besides the missing time calculation, your code has a delayed expansion problem. (My solution below doesn't need delayed expansion)

cmd is incredibly crude when it comes to date/time calculation (it can be done, but...).

Better use the help of another language (like PowerShell):

@echo off
setlocal 
set "filename=last_run.txt"
set "minutes=15"
if not exist "%filename%" (
   break>"%filename%"
   goto :PrintList
)
for /f %%a in ('"powershell Test-Path %filename% -OlderThan (Get-Date).AddMinutes(-%minutes%)"') do set "older=%%a"
if "%older%" == "True" (
  echo %filename% is older than %minutes% minutes; print list
  break>"%filename%"
  goto :PrintList
) else (
  echo %filename% is younger than %minutes% minutes; exiting
  goto :eof
)
:PrintList
echo insert your payload here.
Stephan
  • 53,940
  • 10
  • 58
  • 91
  • given the much simpler solution and less work involved in processing the information into useful form in batch... It's time I started learning more powershell – T3RR0R Feb 18 '20 at 13:50
1

You could use total minutes with a powerhell command.

@echo off
set error=0
if not exist last_run.txt echo File not yet existed, first run will be now & set /a error+=1
    for /f "delims=," %%i in ('powershell -command "(New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalMinutes"') do set "now=%%i"
    if "%error%" == "1" goto :run
    for /f %%a in (last_run.txt) do set earlier=%%a
    set /a result=%now%-%earlier% 
    if %result% geq 15 (
        :run
           echo RUN COMMANDS HERE
           echo %now%>tmp.tmp
    )

The concept is simple. We get the epoch time in minutes. Store the value in a file. Then compare the current minutes with the minutes in the file. if %now% is equal to or more than 15 from %earlier% the command will run. Additionally, if the file does not yet exist, it will create it and run the command first time. From there it will only run if the seconds in the file is 15 or less than current minutes.

Gerhard
  • 22,678
  • 7
  • 27
  • 43
1

Another implementation using from your :

@Echo Off
Set "filename=last_run.txt"
Set "minutes=15"
If Not Exist "%filename%" GoTo :PrintList
"%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile If(((Get-Date)-(Get-Item ".\%filename%").LastWriteTime).Minutes -LT %minutes%){Exit 1}
If ErrorLevel 1 Exit /B
Rem Your payload below here.

:PrintList
CD.>"%filename%"

If you are happy to accept that the PC running this code will always have the appropriate entries in %PATH% and %PATHEXT%, you can change "%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" to just PowerShell.

Compo
  • 36,585
  • 5
  • 27
  • 39