我可以编写一个C#程序 - 当作为计划任务运行时 - 检测任务计划程序何时尝试停止它

时间:2017-08-24 17:40:57

标签: c# windows scheduled-tasks

也许我误解了这部分Windows'任务计划程序用户界面,但以下选项建议(对我而言)程序首先被要求很好地停止,然后在失败时强行退出:

if the running task does not end when requested...

从我心中最深处的角落来看,我记得Windows应用程序可以响应退出的请求;考虑到这一点,我能够谷歌AppDomain.CurrentDomain.ProcessExit。然而,似乎任务计划程序"停止任务......"和AppDomain.CurrentDomain.ProcessExit没有按照我的希望一起工作;这是一个示例程序,我将工作:

放在一起
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 我的问题是:

  1. 可以编写一个程序来响应任务计划程序停止它吗? (或任务计划程序以最粗鲁的方式强制退出任务?)
  2. 如果程序可以以这种方式编写,如何是正确的方法吗? (我尝试的方式显然不正确。)
  3. 我是否过度思考了所有这些,将程序时间本身放在并行线程中会更好? (可能在app.config中设置了最大时间,或者其他。)
  4. [编辑]在Andrew Morton的请求中尝试了这个变体,结果类似:

    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!");
            }
        }
    }
    

    任务计划程序停止任务后,.log文件包含" Hello!"但不是"再见!"

1 个答案:

答案 0 :(得分:1)

处理这个问题的正确方法是假设你的程序突然死亡而没有任何机会运行代码(因为,你知道,它可以 - 让我们说.NET运行时有一个错误触发崩溃)并在程序外部检测到这一点,因此您可以从那里进行邮件发送/日志记录。如果您可以延迟,您仍然可以从程序本身执行此操作:在下一个任务运行时检测到不干净的关闭,然后通知。这比在进程停止时(无论出于何种原因)尝试进行清理/信令更可靠。对于控制台应用程序尤其如此(如果您正在使用这些应用程序),因为通常会doesn't even run any finalizers退出,除非您为其编写代码(AppDomain.ProcessExitConsole.CancelKeyPress并非如此够了,你得走all the way to SetConsoleCtrlHandler)。总而言之,这并没有让我对应用程序本身没有执行的干净退出抱有太多希望。

这不能回答原始问题,即您是否可以检测到任务计划程序发出的停止请求,如果是,则如何检测。我试图确定它是如何工作的,但是我失败了:如果我在任务计划程序下运行一个拒绝退出的控制台应用程序,它会快乐地继续运行,即使我已将其配置为在之后终止10秒或1分钟。 (你不能从界面设置这么短的时间,但你可以从命令行。)我没有测试任务计划程序支持的最短时间,1小时是否有效。如果使用实际的时间表而不是手动触发的任务,事情也会有所不同,我也没有测试过。但是,如果你手动结束一项任务,它肯定只是调用TerminateProcess并且没有给你任何干净退出的机会 - 仅此一点应该是一些动机,不要把你的代码用于信号失败。任务本身。