This version is language-independent, excepted for optional display, and doesn't require lock files.
I've put comments inside the batch itself, feel free to ask for precisions if needed. I've tested it for March and May 2022, it works and doesn't trigger the command more than one time per month.
@echo off
setlocal enableextensions enabledelayedexpansion
REM Get current date. Powershell is used to get values in a fixed order.
for /f "usebackq tokens=1-3 delims=/" %%A in (`PowerShell -Command "& {Get-Date -format "dd/MM/yyyy"}"`) do (
set DD=%%A
set MM=%%B
set YY=%%C
REM Scheduled day.
set EDD=01
)
REM Not during first 3 days after scheduled day? Skip.
set /A maxday=!EDD!+2
if !DD! LEQ !maxday! (
if !DD! GEQ !EDD! (
goto :can_test
)
)
echo !DD!/!MM!/!YY!: Not first days after scheduled day, no need to test.
goto :eof
:can_test
REM Compute day of week: 0=Monday, ... 5=Saturday, 6=Sunday.
set /A c=(14-!MM!)/12
set /A y=!YY!-!c!
set /A m=!MM!+(12*!c!)-2
set /A d=((!EDD!-1+!y!+(!y!/4)-(!y!/100)+(!y!/400)+((31*!m!)/12))) %% 7
REM Get human-readable day. Change according to your own language, if needed. Keep order, of course.
set DAYS=Monday Tuesday Wednesday Thursday Friday Saturday Sunday
set /A i=0
for %%A in (!DAYS!) do (
set DAY=%%A
if !i! EQU !d! goto :found_day
set /A i+=1
)
:found_day
echo Day of week for !EDD!/!MM!/!YY!: !d! ^(!DAY!^)
REM If EDD is during week-end, increase expected day (2 days for Saturday, 1 day for Sunday)..
if !d! GEQ 6 (
set /A EDD+=7-!d!
REM Handle non-significative zero.
if !EDD! LSS 10 (
set EDD=0!EDD!
)
echo On week-end, schedule it to !EDD!/!MM!/!YY! instead.
)
REM Are we on scheduled day EXACTLY?
if !DD! EQU !EDD! (
REM Executing command now.
echo Executing: C:\MyExec\popo.exe arg1 arg2
REM C:\MyExec\popo.exe arg1 arg2
goto :eof
)
REM We're before or after schedule, but still within the first three days in the month.
echo Unscheduled for today ^(!DD!/!MM!/!YY!^).
goto :eof
The "day of week" formula comes from here: Mathematical curiosities / Find the day of the week with a given date (in French).
I took also Gerhard's trick for obtaining a fixed date format quickly through Powershell. It could also have been done with an embedded VBS script, since this language natively have the Weekday
function, but it may have been quite unreadable to add a temporary script generation within the batch itself.