perhaps I'm misinterpreting this part of Windows' Task Scheduler UI, but the following options suggest (to me) that a program is first asked nicely to stop, and then forcefully quit when that fails:
from the deepest corners of my mind, I remembered that Windows applications can respond to requests to quit; with that in mind, I was able to google up AppDomain.CurrentDomain.ProcessExit
. however, it appears that Task Scheduler's "stop the task..." and AppDomain.CurrentDomain.ProcessExit
do not work together as I had hoped; here is an example program I threw together that does not work:
using System;
using System.Threading;
using System.Windows.Forms;
namespace GimmeJustASec
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += new EventHandler(SuddenCleanup);
while(true)
{
Thread.Sleep(1000);
}
}
static void SuddenCleanup(object sender, EventArgs e)
{
MessageBox.Show("Hello!");
}
}
}
tl;dr my question is:
[edit] tried this variant, at Andrew Morton's request, with similar results:
using System;
using System.Threading;
using System.Windows.Forms;
using System.IO;
namespace GimmeJustASec
{
class Program
{
private static StreamWriter _log;
static void Main(string[] args)
{
_log = File.CreateText("GimmeJustASec.log");
_log.AutoFlush = true;
_log.WriteLine("Hello!");
AppDomain.CurrentDomain.ProcessExit += new EventHandler(SuddenCleanup);
while(true)
{
Thread.Sleep(1000);
}
}
static void SuddenCleanup(object sender, EventArgs e)
{
_log.WriteLine("Goodbye!");
}
}
}
after Task Scheduler stops the task, the .log file contains "Hello!" but not "Goodbye!"
Since C language does not support chaining assignment like a=b=c; each assignment operator (=) operates on two operands only.
C+ (grade), an academic grade. C++, a programming language. C with Classes, predecessor to the C++ programming language. ANSI C, a programming language (as opposed to K&R C)
The proper way to handle this is to assume your program can die suddenly and without any chance to run code whatsoever (because, you know, it can -- let's say the .NET runtime has a bug that triggers a crash) and detect this outside the program, so you can do the mailing/logging from there. If you can brook a delay, you can still do this from the program itself: detect an unclean shutdown when the task next runs and then notify. This is tons more reliable than attempting to do cleanup/signaling while the process is going down (for whatever reason). This is especially true for console applications (if you're using those) because exiting those normally doesn't even run any finalizers, unless you write code for it (AppDomain.ProcessExit
and Console.CancelKeyPress
aren't enough, you have to go all the way to SetConsoleCtrlHandler
). All in all, this does not make me have much hope for a clean exit that isn't performed by the application itself.
This does not answer the original question of whether you can detect a request to stop issued by Task Scheduler, and if so, how. I've tried to establish how that works, but I failed: if I run a console application under Task Scheduler that refuses to exit, it will merrily keep on running, even if I've configured it to be terminated after 10 seconds or 1 minute. (You can't set timeouts this short from the interface, but you can from the command line.) I did not test if the minimum time supported by Task Scheduler, 1 hour, works. I've also not tested if things fare differently when using an actual schedule, rather than a manually triggered task. If you manually end a task, though, it defiinitely just calls TerminateProcess
and doesn't give you any chance for a clean exit -- that alone should be some motivation to not put your code for signaling failure in the task itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With