I see I'm not getting any help here. I'm not expecting any quick bug fix from Microsoft either. So I've come up with an alternative way of accomplishing what I want. I'm including 3 .bat scripts that demonstrate my approach. Since this site doesn't permit .bat files as attachments, I've included them inline in this post.
Main.Bat:
:Again
In here I have
various commands that
do some processing that
I want to happen every
6 hours.
rem This places a time stamp in the command window.
Time /t
Call WaitForTimerExpired
GoTo Again
---------------------------------------------------------------------------
WaitForTimerExpired:
echo off
rem Since this script is invoked via Call from Main.Bat, it runs in the same command window.
rem I want it to be silent, hence the echo off.
rem I use the TimeOut command to delay for 6 hours. TimeOut is a delicate command. If a TimeOut is running in a
rem command window & you happen to bring that window into foreground, any keystroke immediately expires the TimeOut.
rem Even Alt+Tab to switch away from the window where the TimeOut is counting down causes the interval to immediately
rem expire. Yes, I know about the /nobreak parameter. You'll see below that I do use it. But I like the idea of being able to
rem trigger my Main.Bat process on demand, before a 6-hour interval might have elapsed. That would be in addition to the
rem possibility of just letting it wait the full 6 hours. In order to let me easily inspect my Main.Bat window without worrying
rem about accidentally expiring the interval, I have isolated the 6-hour TimeOut command in a separate task. That's why
rem I have this perhaps slightly elaborate setup.
rem Launch the timer in a separate task.
Start " " /Min Timer
:PollAgain
rem Even though I have echo off at the top of this script, the TimeOut command insists on displaying its countdown
rem message, even when I had @ at the beginning of the command. I don't want to see that message. So I redirect
rem the countdown message to a file, which I immediately delete.
TimeOut /t 60 /nobreak 1>Junk
erase Junk
If Not Exist Semaphore.Txt (
GoTo PollAgain
) Else (
Erase Semaphore.Txt
)
GoTo SkipComment
This script is invoked by a Call from the Main.Bat script. That means I can't code an Exit in this script. An Exit in this script would terminate Main.Bat as well. When execution gets into the Else above, flow of control falls down to here. The end of the file implicitly returns to Main.Bat. There is no Return command in this language. How silly. Whatever. Deal with it.
The idea here is that at a rhythm of once per minute I check for the existence of the semaphore file. As long as it doesn't exist, the timer is still in the process of counting down. Once the semaphore comes into existence, that's my signal that the timer has expired. And by the way, Timer.Bat has ended. The contents of the file are of no use or interest. I just delete the file & return to the main program, which then loops back around & does its processing again. It then issues another Call for this script.
I wasn't entirely sure to what extent the echo off in this script would affect the calling script. Experimentation shows that echo off persists after this script returns. I don't want that. So I reinstate echo before I go back.
:SkipComment
echo on
---------------------------------------------------------------------------
Timer.Bat:
rem This is the slave timer task for Main.Bat. This isolates the TimeOut command in its own window, thus making it easy to avoid
rem accidentally triggering the premature completion of the wait interval. TimeOut responds to just scrolling its command window
rem & even Alt+Tab. Completing the interval makes the primary process repeat. I don't always want that. So I've isolated the
rem overly sensitive TimeOut command here so the main process can remain in its own command window where I can see when
rem it last ran without accidentally making it run again. But I still have the option of triggering the main task by jostling this window.
Time /t
TimeOut /t 21600
rem This is where I used to issue a Waitfor /si command. I no longer care whether that ever gets fixed. This is the
rem approach I will be using indefinitely.
rem This creates a file that contains the text "Expired" as its only line. The text is of no importance.
rem Only the existence of the file is of any importance.
Type Expired 1>Semaphore.Txt
Exit
---------------------------------------------------------------------------
I really wanted to let the Task Scheduler take care of this. At the time I originally wrote this collection of scripts, I believed it wasn't possible to use the Task Scheduler to schedule a recurring process on a timer whose duration was of my choosing. But I've looked at it again more closely & I believe I actually could do this through the Task Scheduler.
But at this point, it's not worth the bother. What I'm showing above does what I want. It works. I'm not fixing it. If I ever have a need some time in the future for a process that runs on a timer, I'll define it in the Task Scheduler.